flipper-cache-store 0.11.0.beta7

Sign up to get free protection for your applications and to get access to all the features.
@@ -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