abstract_feature_branch 1.3.1 → 1.3.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 52ff8ed098aa83bdd70eda839fa74b291c95993fb9859e2cc5ed8c0752bfa213
4
- data.tar.gz: 9b5e6915905904be0b87690a73b1dfe14ec8893b2659383545bac23b0fe76978
3
+ metadata.gz: 47e99ade543da399fb1529db07bbecd871e23a1eb7cff9239a578067453dc312
4
+ data.tar.gz: b54ab8066e04ee68d6d40940a84dd69f237354d40523e5003be4f34ef6d4e03b
5
5
  SHA512:
6
- metadata.gz: 2f948fd18d057bed300d4cb9eb89e36b784ec2e8a445edaeaf2d742866884828795e8873de02ea9d1794604757dee8d6af2b63934a4f7fcd5b7c0d65aa1171ec
7
- data.tar.gz: c4a1ddc94547f390e2960ddc97a20034cf7bd3dbaa378e17060ae38509b019897d0364913573856254269217c22731de15e7e1e8c8825b1d30c0615521ee6610
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
1
+ # Abstract Feature Branch 1.3.2
2
2
  [![Gem Version](https://badge.fury.io/rb/abstract_feature_branch.png)](http://badge.fury.io/rb/abstract_feature_branch)
3
3
  [![Build Status](https://api.travis-ci.org/AndyObtiva/abstract_feature_branch.png?branch=master)](https://travis-ci.org/AndyObtiva/abstract_feature_branch)
4
4
  [![Coverage Status](https://coveralls.io/repos/AndyObtiva/abstract_feature_branch/badge.png?branch=master)](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.1'</pre>
41
- - With `rails` `~> 2.0` only: Add the following to config/environment.rb <pre>config.gem 'abstract_feature_branch', :version => '1.3.1'</pre>
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.1</pre>
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 optional Redis configuration of `AbstractFeatureBranch.feature_store` in `config/initializers/abstract_feature_branch.rb` (`Redis` `ConnectionPool` instance is recommended for Production environments)
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
+ 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.1 ruby lib
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.1"
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.3.6".freeze
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 ||= initialize_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
- @feature_store = feature_store.is_a?(::ConnectionPool) ? AbstractFeatureBranch::Redis::ConnectionPoolToRedisAdapter.new(feature_store) : feature_store
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 initialize_feature_store
62
- self.feature_store = ::Redis.new
63
- rescue => e
64
- logger.debug { "Redis is not enabled!" }
65
- logger.debug { e.full_message }
66
- nil
67
- end
68
- alias initialize_user_features_storage initialize_feature_store
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, :logger, :logger=, :initialize_logger, :cacheable, :cacheable=, :initialize_cacheable, :feature_store, :feature_store=, :initialize_feature_store, :user_features_storage, :user_features_storage=, :initialize_user_features_storage
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
@@ -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.1
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.3.6
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