abstract_feature_branch 1.3.1 → 1.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/README.md +15 -6
- data/VERSION +1 -1
- data/abstract_feature_branch.gemspec +3 -3
- data/lib/abstract_feature_branch/configuration.rb +20 -10
- data/lib/abstract_feature_branch.rb +9 -4
- data/lib/ext/feature_branch.rb +1 -1
- data/lib/generators/templates/config/initializers/abstract_feature_branch.rb +4 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 47e99ade543da399fb1529db07bbecd871e23a1eb7cff9239a578067453dc312
|
4
|
+
data.tar.gz: b54ab8066e04ee68d6d40940a84dd69f237354d40523e5003be4f34ef6d4e03b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a2d9b1f7a36c405bbb7406bd22b4ec29f0f9d4d55a1ecf7d83ee8adb6f77cba28159f20a32be8b1fa36f97422ccdf74a7f93c6c06d8cb617b0f5405d0d833052
|
7
|
+
data.tar.gz: d851c77683233aa129261171769b8e693949bf178af7c958995daf8f237fed1d7364db8b805e635e5346acdb26c3944af24aab15aab8c5c1f686efa29aba5bcc
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
## 1.3.2
|
4
|
+
|
5
|
+
- Ensure better performance, fetch Redis Overrides at app/server startup time only by default while providing option to fetch live by setting `AbstractFeatureBranch.feature_store_live_fetching` to `true`
|
6
|
+
- Do not automatically pre-init `AbstractFeatureBranch.feature_store` with `Redis.new` if it was `nil` as that is a bad default.
|
7
|
+
- Fix issue with crashing when not including the `connection_pool` gem manually if needed with a version of `redis` older than 5
|
8
|
+
|
3
9
|
## 1.3.1
|
4
10
|
|
5
11
|
- Support Redis `ConnectionPool` `AbstractFeatureBranch::Configuration#feature_store`
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Abstract Feature Branch 1.3.
|
1
|
+
# Abstract Feature Branch 1.3.2
|
2
2
|
[](http://badge.fury.io/rb/abstract_feature_branch)
|
3
3
|
[](https://travis-ci.org/AndyObtiva/abstract_feature_branch)
|
4
4
|
[](https://coveralls.io/r/AndyObtiva/abstract_feature_branch?branch=master)
|
@@ -37,8 +37,8 @@ Setup
|
|
37
37
|
### Rails Application Use
|
38
38
|
|
39
39
|
1. Configure Rubygem
|
40
|
-
- With `rails` between `~> 7.0` and `~> 2.0`: Add the following to Gemfile <pre>gem 'abstract_feature_branch', '~> 1.3.
|
41
|
-
- With `rails` `~> 2.0` only: Add the following to config/environment.rb <pre>config.gem 'abstract_feature_branch', :version => '1.3.
|
40
|
+
- With `rails` between `~> 7.0` and `~> 2.0`: Add the following to Gemfile <pre>gem 'abstract_feature_branch', '~> 1.3.2'</pre>
|
41
|
+
- With `rails` `~> 2.0` only: Add the following to config/environment.rb <pre>config.gem 'abstract_feature_branch', :version => '1.3.2'</pre>
|
42
42
|
2. Generate <code>config/initializers/abstract_feature_branch.rb</code>, <code>lib/tasks/abstract_feature_branch.rake</code>, <code>config/features.yml</code> and <code>config/features.local.yml</code> in your Rails app directory by running <pre>rails g abstract_feature_branch:install</pre>
|
43
43
|
3. [Optional] Generate <code>config/features/[context_path].yml</code> in your Rails app directory by running <pre>rails g abstract_feature_branch:context context_path</pre> (more details under [**instructions**](#instructions))
|
44
44
|
4. [Optional] Customize configuration in <code>config/initializers/abstract_feature_branch.rb</code> (can be useful for changing location of feature files in Rails application, configuring Redis with a Redis or ConnectionPool instance to use for overrides, and per-user feature enablement, or troubleshooting a specific Rails environment feature configuration)
|
@@ -47,7 +47,7 @@ Setup
|
|
47
47
|
|
48
48
|
### Ruby Application General Use
|
49
49
|
|
50
|
-
1. <pre>gem install abstract_feature_branch -v 1.3.
|
50
|
+
1. <pre>gem install abstract_feature_branch -v 1.3.2</pre>
|
51
51
|
2. Add code <code>require 'abstract_feature_branch'</code>
|
52
52
|
3. Create <code>config/features.yml</code> under <code>AbstractFeatureBranch.application_root</code> and fill it with content similar to that of the sample <code>config/features.yml</code> mentioned under [**instructions**](#instructions).
|
53
53
|
4. [Optional] Create <code>config/features.local.yml</code> under <code>AbstractFeatureBranch.application_root</code> (more details under [**instructions**](#instructions))
|
@@ -57,7 +57,8 @@ Setup
|
|
57
57
|
8. [Optional] Add code <code>AbstractFeatureBranch.logger = "[your_application_logger]"</code> (it defaults to a new instance of Ruby <code>Logger</code>. Must use a logger with <code>info</code> and <code>warn</code> methods).
|
58
58
|
9. [Optional] Add code <code>AbstractFeatureBranch.cacheable = {[environment] => [true/false]}</code> to indicate cacheability of loaded feature files for enhanced performance (it defaults to true for every environment other than development).
|
59
59
|
10. [Optional] Add code <code>AbstractFeatureBranch.load_application_features</code> to pre-load application features for improved first-use performance
|
60
|
-
11. [Optional] Add code <code>AbstractFeatureBranch.feature_store = Redis.new(options)</code> to configure Redis for overrides or per-user feature enablement
|
60
|
+
11. [Optional] Add code <code>AbstractFeatureBranch.feature_store = Redis.new(options)</code> to configure Redis for overrides and/or per-user feature enablement
|
61
|
+
12. [Optional] Set <code>AbstractFeatureBranch.feature_store_live_fetching = true</code> to enable live fetching of features from store (e.g. Redis) to avoid need for app/server restart upon feature changes, with the trade-off of slightly more latency due to making calls to feature store over the network
|
61
62
|
|
62
63
|
Instructions
|
63
64
|
------------
|
@@ -262,12 +263,16 @@ application more easily.
|
|
262
263
|
Redis Overrides
|
263
264
|
---------------
|
264
265
|
|
265
|
-
Prerequisites: Redis server and client (`redis` gem) and
|
266
|
+
Prerequisites: Redis server and client (`redis` gem) and Redis configuration of `AbstractFeatureBranch.feature_store` in `config/initializers/abstract_feature_branch.rb` (`Redis` `ConnectionPool` instance is recommended for Production environments)
|
266
267
|
|
267
268
|
To be able to override feature configuration in a production environment, you can utilize Redis Overrides.
|
268
269
|
|
269
270
|
Alternatively, you may use Redis Overrides as your main source of feature configuration if you prefer that instead of relying on YAML files.
|
270
271
|
|
272
|
+
Keep in mind that by default, Redis Overrides are fetched on app/server start to pre-cache for better performance.
|
273
|
+
|
274
|
+
To enable live fetching of Redis Overrides, set `AbstractFeatureBranch#feature_store_live_fetching` to `true` (e.g. in `config/initializers/abstract_feature_branch.rb`), but keep in mind the trade-off with more latency due to making calls to Redis Server over the network.
|
275
|
+
|
271
276
|
You can override feature configuration with Redis hash values by calling `AbstractFeatureBranch#set_store_feature` in `rails console` (or `irb` after requiring `redis` and `abstract_feature_branch`):
|
272
277
|
|
273
278
|
```ruby
|
@@ -358,6 +363,10 @@ Here is the content of the generated initializer [with `redis` client gem added]
|
|
358
363
|
> # The following example line works with Heroku Redis To Go while still operating on local Redis for local development
|
359
364
|
> # AbstractFeatureBranch.feature_store = Redis.new(:url => ENV['REDISTOGO_URL'])
|
360
365
|
>
|
366
|
+
> # Enable live fetching of feature configuration from storage system, to update features without app/server restart.
|
367
|
+
> # false by default to only load features on app/server start for faster performance (requires restart on change)
|
368
|
+
> AbstractFeatureBranch.feature_store_live_fetching = false
|
369
|
+
>
|
361
370
|
> # Application root where config/features.yml or config/features/ is found
|
362
371
|
> AbstractFeatureBranch.application_root = Rails.root
|
363
372
|
>
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.3.
|
1
|
+
1.3.2
|
@@ -2,11 +2,11 @@
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
3
|
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
|
-
# stub: abstract_feature_branch 1.3.
|
5
|
+
# stub: abstract_feature_branch 1.3.2 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "abstract_feature_branch".freeze
|
9
|
-
s.version = "1.3.
|
9
|
+
s.version = "1.3.2"
|
10
10
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
|
12
12
|
s.require_paths = ["lib".freeze]
|
@@ -40,7 +40,7 @@ Gem::Specification.new do |s|
|
|
40
40
|
s.homepage = "http://github.com/AndyObtiva/abstract_feature_branch".freeze
|
41
41
|
s.licenses = ["MIT".freeze]
|
42
42
|
s.post_install_message = "\nRails-only post-install instructions:\n\n1) Run the following command to generate the Rails initializer and basic feature files:\n\nrails g abstract_feature_branch:install\n\n2) Optionally, you may run this command to generate feature files per context:\n\nrails g abstract_feature_branch:context context_path\n \n3) Optionally, install Redis server with [Homebrew](https://brew.sh/) by running:\n\nbrew install redis\n\n4) Optionally, install redis client gem (required with Redis server) by adding the following line to Gemfile above abstract_feature_branch:\n\ngem 'redis', '~> 5.0.5'\n\nAfterwards, run:\n\nbundle\n\n5) Optionally, customize configuration in config/initializers/abstract_feature_branch.rb\n\n(can be useful for changing location of feature files in Rails application,\nconfiguring Redis with a Redis or ConnectionPool instance to use for overrides and per-user feature enablement,\nand/or troubleshooting specific Rails environment feature configurations)\n\n".freeze
|
43
|
-
s.rubygems_version = "3.
|
43
|
+
s.rubygems_version = "3.1.4".freeze
|
44
44
|
s.summary = "abstract_feature_branch is a Rails gem that enables developers to easily branch by abstraction as per this pattern: http://paulhammant.com/blog/branch_by_abstraction.html".freeze
|
45
45
|
|
46
46
|
if s.respond_to? :specification_version then
|
@@ -45,7 +45,7 @@ module AbstractFeatureBranch
|
|
45
45
|
end
|
46
46
|
|
47
47
|
def feature_store
|
48
|
-
@feature_store
|
48
|
+
@feature_store
|
49
49
|
end
|
50
50
|
alias user_features_storage feature_store
|
51
51
|
|
@@ -53,18 +53,28 @@ module AbstractFeatureBranch
|
|
53
53
|
if feature_store.nil?
|
54
54
|
@feature_store = nil
|
55
55
|
else
|
56
|
-
|
56
|
+
begin
|
57
|
+
@feature_store = feature_store.is_a?(::ConnectionPool) ? AbstractFeatureBranch::Redis::ConnectionPoolToRedisAdapter.new(feature_store) : feature_store
|
58
|
+
rescue NameError => e
|
59
|
+
logger.debug { "connection_pool gem is not available" }
|
60
|
+
@feature_store = feature_store
|
61
|
+
end
|
57
62
|
end
|
58
63
|
end
|
59
64
|
alias user_features_storage= feature_store=
|
60
65
|
|
61
|
-
def
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
66
|
+
def feature_store_live_fetching
|
67
|
+
initialize_feature_store_live_fetching if @feature_store_live_fetching.nil?
|
68
|
+
@feature_store_live_fetching
|
69
|
+
end
|
70
|
+
alias feature_store_live_fetching? feature_store_live_fetching
|
71
|
+
|
72
|
+
def feature_store_live_fetching=(value)
|
73
|
+
@feature_store_live_fetching = value
|
74
|
+
end
|
75
|
+
|
76
|
+
def initialize_feature_store_live_fetching
|
77
|
+
@feature_store_live_fetching = false
|
78
|
+
end
|
69
79
|
end
|
70
80
|
end
|
@@ -23,14 +23,16 @@ module AbstractFeatureBranch
|
|
23
23
|
|
24
24
|
class << self
|
25
25
|
extend Forwardable
|
26
|
-
def_delegators :configuration, :application_root, :application_root=, :initialize_application_root, :application_environment, :application_environment=, :initialize_application_environment,
|
26
|
+
def_delegators :configuration, :application_root, :application_root=, :initialize_application_root, :application_environment, :application_environment=, :initialize_application_environment,
|
27
|
+
:logger, :logger=, :initialize_logger, :cacheable, :cacheable=, :initialize_cacheable, :feature_store, :feature_store=, :user_features_storage, :user_features_storage=,
|
28
|
+
:feature_store_live_fetching, :feature_store_live_fetching=
|
27
29
|
|
28
30
|
def configuration
|
29
31
|
@configuration ||= Configuration.new
|
30
32
|
end
|
31
33
|
|
32
34
|
def redis_overrides
|
33
|
-
load_redis_overrides
|
35
|
+
@redis_overrides ||= load_redis_overrides
|
34
36
|
end
|
35
37
|
def load_redis_overrides
|
36
38
|
return {} if feature_store.nil?
|
@@ -39,7 +41,7 @@ module AbstractFeatureBranch
|
|
39
41
|
output.merge(feature => get_store_feature(feature))
|
40
42
|
end
|
41
43
|
|
42
|
-
downcase_keys(redis_feature_hash)
|
44
|
+
@redis_overrides = downcase_keys(redis_feature_hash)
|
43
45
|
end
|
44
46
|
|
45
47
|
def environment_variable_overrides
|
@@ -76,19 +78,22 @@ module AbstractFeatureBranch
|
|
76
78
|
local_features[environment] ||= {}
|
77
79
|
@environment_features[environment] = features[environment].
|
78
80
|
merge(local_features[environment]).
|
79
|
-
merge(environment_variable_overrides)
|
81
|
+
merge(environment_variable_overrides).
|
82
|
+
merge(redis_overrides)
|
80
83
|
end
|
81
84
|
def application_features
|
82
85
|
unload_application_features unless cacheable?
|
83
86
|
environment_features(application_environment)
|
84
87
|
end
|
85
88
|
def load_application_features
|
89
|
+
AbstractFeatureBranch.load_redis_overrides
|
86
90
|
AbstractFeatureBranch.load_environment_variable_overrides
|
87
91
|
AbstractFeatureBranch.load_features
|
88
92
|
AbstractFeatureBranch.load_local_features
|
89
93
|
AbstractFeatureBranch.load_environment_features(application_environment)
|
90
94
|
end
|
91
95
|
def unload_application_features
|
96
|
+
@redis_overrides = nil
|
92
97
|
@environment_variable_overrides = nil
|
93
98
|
@features = nil
|
94
99
|
@local_features = nil
|
data/lib/ext/feature_branch.rb
CHANGED
@@ -10,7 +10,7 @@ class Object
|
|
10
10
|
def self.feature_enabled?(feature_name, user_id = nil)
|
11
11
|
normalized_feature_name = feature_name.to_s.downcase
|
12
12
|
|
13
|
-
redis_override_value = AbstractFeatureBranch.get_store_feature(normalized_feature_name) rescue nil
|
13
|
+
redis_override_value = (AbstractFeatureBranch.get_store_feature(normalized_feature_name) rescue nil) if AbstractFeatureBranch.configuration.feature_store_live_fetching?
|
14
14
|
value = !redis_override_value.nil? ? redis_override_value : AbstractFeatureBranch.application_features[normalized_feature_name]
|
15
15
|
if value == 'per_user'
|
16
16
|
value = !user_id.nil? && AbstractFeatureBranch.user_features_storage.sismember("#{AbstractFeatureBranch::ENV_FEATURE_PREFIX}#{normalized_feature_name}", user_id)
|
@@ -7,6 +7,10 @@
|
|
7
7
|
# The following example line works with Heroku Redis To Go while still operating on local Redis for local development
|
8
8
|
# AbstractFeatureBranch.feature_store = Redis.new(:url => ENV['REDISTOGO_URL'])
|
9
9
|
|
10
|
+
# Enable live fetching of feature configuration from storage system, to update features without app/server restart.
|
11
|
+
# false by default to only load features on app/server start for faster performance (requires restart on change)
|
12
|
+
AbstractFeatureBranch.feature_store_live_fetching = false
|
13
|
+
|
10
14
|
# Application root where config/features.yml or config/features/ is found
|
11
15
|
AbstractFeatureBranch.application_root = Rails.root
|
12
16
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: abstract_feature_branch
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.3.
|
4
|
+
version: 1.3.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Annas "Andy" Maleh
|
@@ -168,7 +168,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
168
168
|
- !ruby/object:Gem::Version
|
169
169
|
version: '0'
|
170
170
|
requirements: []
|
171
|
-
rubygems_version: 3.
|
171
|
+
rubygems_version: 3.1.4
|
172
172
|
signing_key:
|
173
173
|
specification_version: 4
|
174
174
|
summary: 'abstract_feature_branch is a Rails gem that enables developers to easily
|