flipper-cache-store 0.11.0.beta7

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e05826a8bee645823d83c2fc1497001a21061cb3
4
+ data.tar.gz: 4b57d8c399fe0025e17ba36dc668f76fa78b77a1
5
+ SHA512:
6
+ metadata.gz: 6b90ec6e64f7aeb62fef75403f52ba9c823ee3d67b9a46cdfd74a2430b2f2effba63dc343392c91348b7338dbbcb3cbd5db8bda479a2f2181224c8f0731e8c4c
7
+ data.tar.gz: b7b502a2905d855a4a79d060e12b96e60ebc282494ede5aa5281953f13e3b6c9181cbe52bb43964fe3e58bcad283ed42376dd749e451e94f945531c1b70f9cd9
@@ -0,0 +1,99 @@
1
+ # Flipper CacheStore
2
+
3
+ A [CacheStore](http://api.rubyonrails.org/classes/ActiveSupport/Cache/Store.html) adapter for [Flipper](https://github.com/jnunemaker/flipper).
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'flipper-cache-store'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself with:
16
+
17
+ $ gem install flipper-cache-store
18
+
19
+ ## Usage
20
+
21
+ ```ruby
22
+ require 'active_support/cache'
23
+ require 'flipper/adapters/memory'
24
+ require 'flipper/adapters/cache_store'
25
+
26
+ memory_adapter = Flipper::Adapters::Memory.new
27
+ cache = ActiveSupport::Cache::MemoryStore.new
28
+ adapter = Flipper::Adapters::CacheStore.new(memory_adapter, cache, expires_in: 5.minutes)
29
+ flipper = Flipper.new(adapter)
30
+ ```
31
+ Setting `expires_in` is optional and will set an expiration time on Flipper cache keys. If specified, all flipper keys will use this `expires_in` over the `expires_in` passed to your ActiveSupport cache constructor.
32
+
33
+ ## Internals
34
+
35
+ Each feature is stored in the underlying cache store.
36
+
37
+ This is an example using `ActiveSupport::Cache::MemoryStore` with the [Flipper memory adapter](https://github.com/jnunemaker/flipper/blob/master/lib/flipper/adapters/memory.rb).
38
+
39
+ Each key is namespaced under `flipper/v1/feature/`
40
+
41
+ ```ruby
42
+ require 'active_support/cache'
43
+ require 'flipper/adapters/memory'
44
+ require 'flipper/adapters/cache_store'
45
+
46
+ memory_adapter = Flipper::Adapters::Memory.new
47
+ cache = ActiveSupport::Cache::MemoryStore.new
48
+ adapter = Flipper::Adapters::CacheStore.new(memory_adapter, cache)
49
+ flipper = Flipper.new(adapter)
50
+
51
+ # Register a few groups.
52
+ Flipper.register(:admins) { |thing| thing.admin? }
53
+ Flipper.register(:early_access) { |thing| thing.early_access? }
54
+
55
+ # Create a user class that has flipper_id instance method.
56
+ User = Struct.new(:flipper_id)
57
+
58
+ flipper[:stats].enable
59
+ flipper[:stats].enable_group :admins
60
+ flipper[:stats].enable_group :early_access
61
+ flipper[:stats].enable_actor User.new('25')
62
+ flipper[:stats].enable_actor User.new('90')
63
+ flipper[:stats].enable_actor User.new('180')
64
+ flipper[:stats].enable_percentage_of_time 15
65
+ flipper[:stats].enable_percentage_of_actors 45
66
+ flipper[:search].enable
67
+
68
+ # reading all feature keys
69
+ pp cache.read("flipper/v1/features")
70
+ #<Set: {"stats", "search"}>
71
+
72
+ # reading a single feature
73
+ pp cache.read("flipper/v1/feature/stats")
74
+ {
75
+ :boolean=>"true",
76
+ :groups=>#<Set: {"admins", "early_access"}>,
77
+ :actors=>#<Set: {"25", "90", "180"}>,
78
+ :percentage_of_actors=>"45",
79
+ :percentage_of_time=>"15"
80
+ }
81
+
82
+ # flipper get of feature
83
+ pp adapter.get(flipper[:stats])
84
+ {
85
+ :boolean=>"true",
86
+ :groups=>#<Set: {"admins", "early_access"}>,
87
+ :actors=>#<Set: {"25", "90", "180"}>,
88
+ :percentage_of_actors=>"45",
89
+ :percentage_of_time=>"15"
90
+ }
91
+ ```
92
+
93
+ ## Contributing
94
+
95
+ 1. Fork it
96
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
97
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
98
+ 4. Push to the branch (`git push origin my-new-feature`)
99
+ 5. Create new Pull Request
@@ -0,0 +1,104 @@
1
+ module Flipper
2
+ module Adapters
3
+ # Public: Adapter that wraps another adapter with the ability to cache
4
+ # adapter calls in ActiveSupport::CacheStore caches.
5
+ #
6
+ class CacheStore
7
+ include ::Flipper::Adapter
8
+
9
+ Version = 'v1'.freeze
10
+ Namespace = "flipper/#{Version}".freeze
11
+ FeaturesKey = "#{Namespace}/features".freeze
12
+
13
+ # Private
14
+ def self.key_for(key)
15
+ "#{Namespace}/feature/#{key}"
16
+ end
17
+
18
+ # Internal
19
+ attr_reader :cache
20
+
21
+ # Public: The name of the adapter.
22
+ attr_reader :name
23
+
24
+ # Public
25
+ def initialize(adapter, cache, expires_in: nil)
26
+ @adapter = adapter
27
+ @name = :cache_store
28
+ @cache = cache
29
+ @write_options = {}
30
+ @write_options.merge!(expires_in: expires_in) if expires_in
31
+ end
32
+
33
+ # Public
34
+ def features
35
+ @cache.fetch(FeaturesKey, @write_options) do
36
+ @adapter.features
37
+ end
38
+ end
39
+
40
+ # Public
41
+ def add(feature)
42
+ result = @adapter.add(feature)
43
+ @cache.delete(FeaturesKey)
44
+ result
45
+ end
46
+
47
+ ## Public
48
+ def remove(feature)
49
+ result = @adapter.remove(feature)
50
+ @cache.delete(FeaturesKey)
51
+ @cache.delete(key_for(feature.key))
52
+ result
53
+ end
54
+
55
+ ## Public
56
+ def clear(feature)
57
+ result = @adapter.clear(feature)
58
+ @cache.delete(key_for(feature.key))
59
+ result
60
+ end
61
+
62
+ ## Public
63
+ def get(feature)
64
+ @cache.fetch(key_for(feature.key), @write_options) do
65
+ @adapter.get(feature)
66
+ end
67
+ end
68
+
69
+ def get_multi(features)
70
+ keys = features.map { |feature| key_for(feature.key) }
71
+ result = @cache.read_multi(keys)
72
+ uncached_features = features.reject { |feature| result[feature.key] }
73
+ if uncached_features.any?
74
+ response = @adapter.get_multi(uncached_features)
75
+ response.each do |key, value|
76
+ @cache.write(key_for(key), value, @write_options)
77
+ result[key] = value
78
+ end
79
+ end
80
+ result
81
+ end
82
+
83
+ ## Public
84
+ def enable(feature, gate, thing)
85
+ result = @adapter.enable(feature, gate, thing)
86
+ @cache.delete(key_for(feature.key))
87
+ result
88
+ end
89
+
90
+ ## Public
91
+ def disable(feature, gate, thing)
92
+ result = @adapter.disable(feature, gate, thing)
93
+ @cache.delete(key_for(feature.key))
94
+ result
95
+ end
96
+
97
+ private
98
+
99
+ def key_for(key)
100
+ self.class.key_for(key)
101
+ end
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,3 @@
1
+ module Flipper
2
+ VERSION = '0.11.0.beta7'.freeze
3
+ end
@@ -0,0 +1,50 @@
1
+ require 'helper'
2
+ require 'active_support/cache'
3
+ require 'flipper/adapters/memory'
4
+ require 'flipper/adapters/cache_store'
5
+ require 'flipper/spec/shared_adapter_specs'
6
+
7
+ RSpec.describe Flipper::Adapters::CacheStore do
8
+ let(:memory_adapter) { Flipper::Adapters::Memory.new }
9
+ let(:cache) { ActiveSupport::Cache::MemoryStore.new }
10
+ let(:adapter) { described_class.new(memory_adapter, cache) }
11
+ let(:flipper) { Flipper.new(adapter) }
12
+
13
+ subject { adapter }
14
+
15
+ it_should_behave_like 'a flipper adapter'
16
+
17
+ describe '#remove' do
18
+ it 'expires feature' do
19
+ feature = flipper[:stats]
20
+ adapter.get(feature)
21
+ adapter.remove(feature)
22
+ expect(cache.read(described_class.key_for(feature))).to be(nil)
23
+ end
24
+ end
25
+
26
+ describe '#get_multi' do
27
+ it 'warms uncached features' do
28
+ stats = flipper[:stats]
29
+ search = flipper[:search]
30
+ other = flipper[:other]
31
+ stats.enable
32
+ search.enable
33
+
34
+ adapter.get(stats)
35
+ expect(cache.read(described_class.key_for(search))).to be(nil)
36
+ expect(cache.read(described_class.key_for(other))).to be(nil)
37
+
38
+ adapter.get_multi([stats, search, other])
39
+
40
+ expect(cache.read(described_class.key_for(search))[:boolean]).to eq('true')
41
+ expect(cache.read(described_class.key_for(other))[:boolean]).to be(nil)
42
+ end
43
+ end
44
+
45
+ describe '#name' do
46
+ it 'is cache_store' do
47
+ expect(subject.name).to be(:cache_store)
48
+ end
49
+ end
50
+ end
metadata ADDED
@@ -0,0 +1,83 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: flipper-cache-store
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.11.0.beta7
5
+ platform: ruby
6
+ authors:
7
+ - John Nunemaker
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-07-26 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: flipper
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.11.0.beta7
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.11.0.beta7
27
+ - !ruby/object:Gem::Dependency
28
+ name: activesupport
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '3.2'
34
+ - - "<"
35
+ - !ruby/object:Gem::Version
36
+ version: '6'
37
+ type: :runtime
38
+ prerelease: false
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: '3.2'
44
+ - - "<"
45
+ - !ruby/object:Gem::Version
46
+ version: '6'
47
+ description: ActiveSupport::Cache::Store adapter for Flipper
48
+ email:
49
+ - nunemaker@gmail.com
50
+ executables: []
51
+ extensions: []
52
+ extra_rdoc_files: []
53
+ files:
54
+ - docs/cache_store/README.md
55
+ - lib/flipper/adapters/cache_store.rb
56
+ - lib/flipper/version.rb
57
+ - spec/flipper/adapters/cache_store_spec.rb
58
+ homepage: https://github.com/jnunemaker/flipper
59
+ licenses:
60
+ - MIT
61
+ metadata: {}
62
+ post_install_message:
63
+ rdoc_options: []
64
+ require_paths:
65
+ - lib
66
+ required_ruby_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ required_rubygems_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">"
74
+ - !ruby/object:Gem::Version
75
+ version: 1.3.1
76
+ requirements: []
77
+ rubyforge_project:
78
+ rubygems_version: 2.5.2
79
+ signing_key:
80
+ specification_version: 4
81
+ summary: ActiveSupport::Cache::Store adapter for Flipper
82
+ test_files:
83
+ - spec/flipper/adapters/cache_store_spec.rb