From 529e1b8bd3aa8ed3783261d8d63f26648e5ce43c Mon Sep 17 00:00:00 2001 From: Campbell Allen Date: Tue, 20 Dec 2016 17:39:51 +0000 Subject: [PATCH 01/14] get adapter tests working with docker docker-compose run --rm app bundle exec rake test --- test/adapters/dalli_test.rb | 3 ++- test/adapters/mongo_test.rb | 2 +- test/adapters/redis_test.rb | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/test/adapters/dalli_test.rb b/test/adapters/dalli_test.rb index 1be510238..bb903cc8c 100644 --- a/test/adapters/dalli_test.rb +++ b/test/adapters/dalli_test.rb @@ -6,7 +6,8 @@ class DalliTest < MiniTest::Test prepend Flipper::Test::SharedAdapterTests def setup - @cache = Dalli::Client.new('localhost:11211') + url = ENV.fetch('BOXEN_MEMCACHED_URL', 'localhost:11211') + @cache = Dalli::Client.new(url) @cache.flush memory_adapter = Flipper::Adapters::Memory.new @adapter = Flipper::Adapters::Dalli.new(memory_adapter, @cache) diff --git a/test/adapters/mongo_test.rb b/test/adapters/mongo_test.rb index bbdb504f1..a96cb238f 100644 --- a/test/adapters/mongo_test.rb +++ b/test/adapters/mongo_test.rb @@ -5,7 +5,7 @@ class MongoTest < MiniTest::Test prepend Flipper::Test::SharedAdapterTests def setup - host = '127.0.0.1' + host = ENV.fetch('BOXEN_MONGODB_HOST', '127.0.0.1') port = '27017' logger = Logger.new("/dev/null") collection = Mongo::Client.new(["#{host}:#{port}"], server_selection_timeout: 1, database: 'testing', logger: logger)['testing'] diff --git a/test/adapters/redis_test.rb b/test/adapters/redis_test.rb index b626c9542..d4bdd116e 100644 --- a/test/adapters/redis_test.rb +++ b/test/adapters/redis_test.rb @@ -5,7 +5,8 @@ class RedisTest < MiniTest::Test prepend Flipper::Test::SharedAdapterTests def setup - client = Redis.new({}).tap { |c| c.flushdb } + url = ENV.fetch('BOXEN_REDIS_URL', 'localhost:6379') + client = Redis.new({url: url}).tap { |c| c.flushdb } @adapter = Flipper::Adapters::Redis.new(client) end end From 191a0db6aff072943f2e96192edfdab956fde5bb Mon Sep 17 00:00:00 2001 From: Campbell Allen Date: Tue, 20 Dec 2016 17:51:26 +0000 Subject: [PATCH 02/14] copy interface from dalli for redis_cache --- lib/flipper/adapters/redis_cache.rb | 106 ++++++++++++++++++++++ spec/flipper/adapters/redis_cache_spec.rb | 62 +++++++++++++ 2 files changed, 168 insertions(+) create mode 100644 lib/flipper/adapters/redis_cache.rb create mode 100644 spec/flipper/adapters/redis_cache_spec.rb diff --git a/lib/flipper/adapters/redis_cache.rb b/lib/flipper/adapters/redis_cache.rb new file mode 100644 index 000000000..4661eb16f --- /dev/null +++ b/lib/flipper/adapters/redis_cache.rb @@ -0,0 +1,106 @@ +require 'redis' + +module Flipper + module Adapters + # Public: Adapter that wraps another adapter with the ability to cache + # adapter calls in Redis + class RedisCache + include ::Flipper::Adapter + + Version = "v1".freeze + Namespace = "flipper/#{Version}".freeze + FeaturesKey = "#{Namespace}/features".freeze + + # Private + def self.key_for(key) + "#{Namespace}/feature/#{key}" + end + + # Internal + attr_reader :cache + + # Public: The name of the adapter. + attr_reader :name + + # Public + def initialize(adapter, cache, ttl = 0) + @adapter = adapter + @name = :redis + @cache = cache + @ttl = ttl + end + + # Public + def features + @cache.fetch(FeaturesKey, @ttl) do + @adapter.features + end + end + + # Public + def add(feature) + result = @adapter.add(feature) + @cache.delete(FeaturesKey) + result + end + + # Public + def remove(feature) + result = @adapter.remove(feature) + @cache.delete(FeaturesKey) + @cache.delete(key_for(feature.key)) + result + end + + # Public + def clear(feature) + result = @adapter.clear(feature) + @cache.delete(key_for(feature.key)) + result + end + + # Public + def get(feature) + @cache.fetch(key_for(feature.key), @ttl) do + @adapter.get(feature) + end + end + + def get_multi(features) + keys = features.map { |feature| key_for(feature.key) } + result = @cache.get_multi(keys) + uncached_features = features.reject { |feature| result[key_for(feature.key)] } + + if uncached_features.any? + response = @adapter.get_multi(uncached_features) + response.each do |key, value| + @cache.set(key_for(key), value, @ttl) + result[key] = value + end + end + + result + end + + # Public + def enable(feature, gate, thing) + result = @adapter.enable(feature, gate, thing) + @cache.delete(key_for(feature.key)) + result + end + + # Public + def disable(feature, gate, thing) + result = @adapter.disable(feature, gate, thing) + @cache.delete(key_for(feature.key)) + result + end + + private + + def key_for(key) + self.class.key_for(key) + end + end + end +end diff --git a/spec/flipper/adapters/redis_cache_spec.rb b/spec/flipper/adapters/redis_cache_spec.rb new file mode 100644 index 000000000..18b9f7e4e --- /dev/null +++ b/spec/flipper/adapters/redis_cache_spec.rb @@ -0,0 +1,62 @@ +require 'helper' +require 'flipper/adapters/redis_cache' +require 'flipper/spec/shared_adapter_specs' + +RSpec.describe Flipper::Adapters::RedisCache do + let(:client) { + options = {} + + if ENV['BOXEN_REDIS_URL'] + options[:url] = ENV['BOXEN_REDIS_URL'] + end + + Redis.new(options) + } + + let(:memory_adapter) { Flipper::Adapters::Memory.new } + let(:cache) { Redis.new({url: ENV.fetch('BOXEN_REDIS_URL', 'localhost:6379')})} + let(:adapter) { Flipper::Adapters::RedisCache.new(memory_adapter, cache) } + let(:flipper) { Flipper.new(adapter) } + + subject { described_class.new(adapter, cache) } + + before do + client.flushdb + end + + it_should_behave_like 'a flipper adapter' + + describe "#remove", :focus do + it "expires feature" do + feature = flipper[:stats] + adapter.get(feature) + adapter.remove(feature) + expect(cache.get(described_class.key_for(feature))).to be(nil) + end + end + + describe "#get_multi" do + it "warms uncached features" do + stats = flipper[:stats] + search = flipper[:search] + other = flipper[:other] + stats.enable + search.enable + + adapter.get(stats) + expect(cache.get(described_class.key_for(search))).to be(nil) + expect(cache.get(described_class.key_for(other))).to be(nil) + + adapter.get_multi([stats, search, other]) + + expect(cache.get(described_class.key_for(search))[:boolean]).to eq("true") + expect(cache.get(described_class.key_for(other))[:boolean]).to be(nil) + end + end + + describe "#name" do + it "is dalli" do + expect(subject.name).to be(:dalli) + end + end +end From b2ee475d0e70d6de72cb2e6b2b9c1c60ac4153e6 Mon Sep 17 00:00:00 2001 From: Campbell Allen Date: Thu, 5 Jan 2017 21:19:18 +0000 Subject: [PATCH 03/14] add testing setup / run instructions --- docs/DockerCompose.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/DockerCompose.md b/docs/DockerCompose.md index 8266d19a6..77c460969 100644 --- a/docs/DockerCompose.md +++ b/docs/DockerCompose.md @@ -7,9 +7,11 @@ new contributor could start working on code with a minumum efforts. ## Steps: 1. Install Docker Compose https://docs.docker.com/compose/install -2. Install gems `docker-compose run --rm app bundle install` -3. Run specs `docker-compose run --rm app bundle exec rspec` -4. Optional: log in to container an using a bash for running specs +1. Build the app container `docker-compose build` +1. Install gems `docker-compose run --rm app bundle install` +1. Run specs `docker-compose run --rm app bundle exec rspec` +1. Run tests `docker-compose run --rm app bundle exec rake test` +1. Optional: log in to container an using a bash for running specs ```sh docker-compose run --rm app bash bundle exec rspec From e1a578ec647b76c75a4867d0f57c5589a41d1e76 Mon Sep 17 00:00:00 2001 From: Campbell Allen Date: Fri, 6 Jan 2017 12:25:52 +0000 Subject: [PATCH 04/14] 60 mins default ttl --- lib/flipper/adapters/redis_cache.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/flipper/adapters/redis_cache.rb b/lib/flipper/adapters/redis_cache.rb index 4661eb16f..5d3ecc561 100644 --- a/lib/flipper/adapters/redis_cache.rb +++ b/lib/flipper/adapters/redis_cache.rb @@ -23,7 +23,7 @@ def self.key_for(key) attr_reader :name # Public - def initialize(adapter, cache, ttl = 0) + def initialize(adapter, cache, ttl = 3600) @adapter = adapter @name = :redis @cache = cache From 118e5e89b8d59c3a1b4fba80cbcf35fc00eb5d2b Mon Sep 17 00:00:00 2001 From: Campbell Allen Date: Fri, 6 Jan 2017 12:26:29 +0000 Subject: [PATCH 05/14] implement redis cache remove --- lib/flipper/adapters/redis_cache.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/flipper/adapters/redis_cache.rb b/lib/flipper/adapters/redis_cache.rb index 5d3ecc561..881ab4625 100644 --- a/lib/flipper/adapters/redis_cache.rb +++ b/lib/flipper/adapters/redis_cache.rb @@ -47,8 +47,8 @@ def add(feature) # Public def remove(feature) result = @adapter.remove(feature) - @cache.delete(FeaturesKey) - @cache.delete(key_for(feature.key)) + @cache.del(FeaturesKey) + @cache.del(key_for(feature.key)) result end From bea39f224f6e222a5fc211fadc3e5df0cbae5ebc Mon Sep 17 00:00:00 2001 From: Campbell Allen Date: Fri, 6 Jan 2017 12:28:00 +0000 Subject: [PATCH 06/14] mimic dalli fetch method use marshal to handle objects with the setex redis command --- lib/flipper/adapters/redis_cache.rb | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/lib/flipper/adapters/redis_cache.rb b/lib/flipper/adapters/redis_cache.rb index 881ab4625..a259fd64c 100644 --- a/lib/flipper/adapters/redis_cache.rb +++ b/lib/flipper/adapters/redis_cache.rb @@ -32,7 +32,7 @@ def initialize(adapter, cache, ttl = 3600) # Public def features - @cache.fetch(FeaturesKey, @ttl) do + fetch(FeaturesKey) do @adapter.features end end @@ -61,7 +61,7 @@ def clear(feature) # Public def get(feature) - @cache.fetch(key_for(feature.key), @ttl) do + fetch(key_for(feature.key)) do @adapter.get(feature) end end @@ -101,6 +101,16 @@ def disable(feature, gate, thing) def key_for(key) self.class.key_for(key) end + + def fetch(key, &block) + if cached = @cache.get(key) + return Marshal.load(cached) + else + to_cache = block.call + @cache.setex(key, @ttl, Marshal.dump(to_cache)) + to_cache + end + end end end end From c35ffda232b9ed7f3e54aff467409ff4f708b741 Mon Sep 17 00:00:00 2001 From: Campbell Allen Date: Fri, 6 Jan 2017 16:18:12 +0000 Subject: [PATCH 07/14] implement rest of redis_cache adapter --- lib/flipper/adapters/redis_cache.rb | 29 ++++++++++++++--------- spec/flipper/adapters/redis_cache_spec.rb | 17 +++++++------ 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/lib/flipper/adapters/redis_cache.rb b/lib/flipper/adapters/redis_cache.rb index a259fd64c..a1a5bb528 100644 --- a/lib/flipper/adapters/redis_cache.rb +++ b/lib/flipper/adapters/redis_cache.rb @@ -25,7 +25,7 @@ def self.key_for(key) # Public def initialize(adapter, cache, ttl = 3600) @adapter = adapter - @name = :redis + @name = :redis_cache @cache = cache @ttl = ttl end @@ -40,7 +40,7 @@ def features # Public def add(feature) result = @adapter.add(feature) - @cache.delete(FeaturesKey) + @cache.del(FeaturesKey) result end @@ -55,7 +55,7 @@ def remove(feature) # Public def clear(feature) result = @adapter.clear(feature) - @cache.delete(key_for(feature.key)) + @cache.del(key_for(feature.key)) result end @@ -67,32 +67,35 @@ def get(feature) end def get_multi(features) - keys = features.map { |feature| key_for(feature.key) } - result = @cache.get_multi(keys) - uncached_features = features.reject { |feature| result[key_for(feature.key)] } + keys = features.map { |feature| feature.key } + cache_keys = keys.map { |key| key_for(key) } + cached_features = @cache.mget(cache_keys).map do |value| + value ? Marshal.load(value) : nil + end + result = Hash[keys.zip(cached_features)] + uncached_features = features.reject { |feature| result[feature.key] } if uncached_features.any? response = @adapter.get_multi(uncached_features) response.each do |key, value| - @cache.set(key_for(key), value, @ttl) + set_with_ttl(key_for(key), value) result[key] = value end end - result end # Public def enable(feature, gate, thing) result = @adapter.enable(feature, gate, thing) - @cache.delete(key_for(feature.key)) + @cache.del(key_for(feature.key)) result end # Public def disable(feature, gate, thing) result = @adapter.disable(feature, gate, thing) - @cache.delete(key_for(feature.key)) + @cache.del(key_for(feature.key)) result end @@ -107,10 +110,14 @@ def fetch(key, &block) return Marshal.load(cached) else to_cache = block.call - @cache.setex(key, @ttl, Marshal.dump(to_cache)) + set_with_ttl(key, to_cache) to_cache end end + + def set_with_ttl(key, value) + @cache.setex(key, @ttl, Marshal.dump(value)) + end end end end diff --git a/spec/flipper/adapters/redis_cache_spec.rb b/spec/flipper/adapters/redis_cache_spec.rb index 18b9f7e4e..3bfaf457e 100644 --- a/spec/flipper/adapters/redis_cache_spec.rb +++ b/spec/flipper/adapters/redis_cache_spec.rb @@ -14,11 +14,11 @@ } let(:memory_adapter) { Flipper::Adapters::Memory.new } - let(:cache) { Redis.new({url: ENV.fetch('BOXEN_REDIS_URL', 'localhost:6379')})} + let(:cache) { Redis.new({url: ENV.fetch('BOXEN_REDIS_URL', 'localhost:6379')}) } let(:adapter) { Flipper::Adapters::RedisCache.new(memory_adapter, cache) } let(:flipper) { Flipper.new(adapter) } - subject { described_class.new(adapter, cache) } + subject { adapter } before do client.flushdb @@ -26,7 +26,7 @@ it_should_behave_like 'a flipper adapter' - describe "#remove", :focus do + describe "#remove" do it "expires feature" do feature = flipper[:stats] adapter.get(feature) @@ -49,14 +49,17 @@ adapter.get_multi([stats, search, other]) - expect(cache.get(described_class.key_for(search))[:boolean]).to eq("true") - expect(cache.get(described_class.key_for(other))[:boolean]).to be(nil) + search_cache_value, other_cache_value = [search, other].map do |f| + Marshal.load(cache.get(described_class.key_for(f))) + end + expect(search_cache_value[:boolean]).to eq("true") + expect(other_cache_value[:boolean]).to be(nil) end end describe "#name" do - it "is dalli" do - expect(subject.name).to be(:dalli) + it "is redis_cache" do + expect(subject.name).to be(:redis_cache) end end end From f67c1b4f78af5db5e27daa1d22340a6c8cef3f7a Mon Sep 17 00:00:00 2001 From: Campbell Allen Date: Fri, 6 Jan 2017 16:19:32 +0000 Subject: [PATCH 08/14] =?UTF-8?q?don=E2=80=99t=20wrap=20the=20dalli=20adap?= =?UTF-8?q?ter=20in=20a=20dalli=20adapter?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit use the adapter in the let block to pass into the shared helpers --- spec/flipper/adapters/dalli_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/flipper/adapters/dalli_spec.rb b/spec/flipper/adapters/dalli_spec.rb index ceeb09dd3..e2c45ba36 100644 --- a/spec/flipper/adapters/dalli_spec.rb +++ b/spec/flipper/adapters/dalli_spec.rb @@ -9,7 +9,7 @@ let(:adapter) { Flipper::Adapters::Dalli.new(memory_adapter, cache) } let(:flipper) { Flipper.new(adapter) } - subject { described_class.new(adapter, cache) } + subject { adapter } before do cache.flush From 4ace63b0b5c7e4e16a669d83294689f2145a0bf6 Mon Sep 17 00:00:00 2001 From: Campbell Allen Date: Fri, 6 Jan 2017 16:19:55 +0000 Subject: [PATCH 09/14] require pry for debugging --- spec/helper.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/spec/helper.rb b/spec/helper.rb index 83000b8cc..9ecfaec6a 100644 --- a/spec/helper.rb +++ b/spec/helper.rb @@ -6,6 +6,7 @@ require 'rubygems' require 'bundler' +require 'pry' Bundler.setup(:default) From 61fc237e3a110f7b05f20469a30be84a40b226d7 Mon Sep 17 00:00:00 2001 From: Campbell Allen Date: Fri, 6 Jan 2017 16:26:02 +0000 Subject: [PATCH 10/14] extract cache multi get method --- lib/flipper/adapters/redis_cache.rb | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/lib/flipper/adapters/redis_cache.rb b/lib/flipper/adapters/redis_cache.rb index a1a5bb528..6d0312261 100644 --- a/lib/flipper/adapters/redis_cache.rb +++ b/lib/flipper/adapters/redis_cache.rb @@ -68,12 +68,10 @@ def get(feature) def get_multi(features) keys = features.map { |feature| feature.key } - cache_keys = keys.map { |key| key_for(key) } - cached_features = @cache.mget(cache_keys).map do |value| - value ? Marshal.load(value) : nil + result = Hash[keys.zip(multi_cache_get(keys))] + uncached_features = features.reject do |feature| + result[feature.key] end - result = Hash[keys.zip(cached_features)] - uncached_features = features.reject { |feature| result[feature.key] } if uncached_features.any? response = @adapter.get_multi(uncached_features) @@ -118,6 +116,13 @@ def fetch(key, &block) def set_with_ttl(key, value) @cache.setex(key, @ttl, Marshal.dump(value)) end + + def multi_cache_get(keys) + cache_keys = keys.map { |key| key_for(key) } + @cache.mget(cache_keys).map do |value| + value ? Marshal.load(value) : nil + end + end end end end From 3d1eadd33a9932882e29b90f92eb1b3f9e9afd37 Mon Sep 17 00:00:00 2001 From: Campbell Allen Date: Fri, 6 Jan 2017 16:31:58 +0000 Subject: [PATCH 11/14] consistent formatting --- test/adapters/redis_test.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/adapters/redis_test.rb b/test/adapters/redis_test.rb index d4bdd116e..ca3eb5811 100644 --- a/test/adapters/redis_test.rb +++ b/test/adapters/redis_test.rb @@ -6,7 +6,7 @@ class RedisTest < MiniTest::Test def setup url = ENV.fetch('BOXEN_REDIS_URL', 'localhost:6379') - client = Redis.new({url: url}).tap { |c| c.flushdb } - @adapter = Flipper::Adapters::Redis.new(client) + client = Redis.new({url: url}).tap { |c| c.flushdb } + @adapter = Flipper::Adapters::Redis.new(client) end end From 5c72752e175bcb36a7404bdb068a943fec1dff2b Mon Sep 17 00:00:00 2001 From: Campbell Allen Date: Fri, 6 Jan 2017 16:32:45 +0000 Subject: [PATCH 12/14] add minitest for redis_cache adapter --- test/adapters/redis_cache_test.rb | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 test/adapters/redis_cache_test.rb diff --git a/test/adapters/redis_cache_test.rb b/test/adapters/redis_cache_test.rb new file mode 100644 index 000000000..ec69a755f --- /dev/null +++ b/test/adapters/redis_cache_test.rb @@ -0,0 +1,18 @@ +require 'test_helper' +require 'flipper/adapters/memory' +require 'flipper/adapters/redis_cache' + +class DalliTest < MiniTest::Test + prepend Flipper::Test::SharedAdapterTests + + def setup + url = ENV.fetch('BOXEN_REDIS_URL', 'localhost:6379') + @cache = Redis.new({url: url}).tap { |c| c.flushdb } + memory_adapter = Flipper::Adapters::Memory.new + @adapter = Flipper::Adapters::RedisCache.new(memory_adapter, @cache) + end + + def teardown + @cache.flushdb + end +end From 879f077f44782ff52b39912fdd561b94ff5c5ecc Mon Sep 17 00:00:00 2001 From: Campbell Allen Date: Fri, 6 Jan 2017 16:52:38 +0000 Subject: [PATCH 13/14] remove pry require as it breaks the tests --- spec/helper.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/spec/helper.rb b/spec/helper.rb index 9ecfaec6a..83000b8cc 100644 --- a/spec/helper.rb +++ b/spec/helper.rb @@ -6,7 +6,6 @@ require 'rubygems' require 'bundler' -require 'pry' Bundler.setup(:default) From 2100398884bd14e361de408643e7bd4cd4838a64 Mon Sep 17 00:00:00 2001 From: Campbell Allen Date: Fri, 6 Jan 2017 16:58:17 +0000 Subject: [PATCH 14/14] add redis uri scheme --- spec/flipper/adapters/redis_cache_spec.rb | 2 +- test/adapters/redis_cache_test.rb | 2 +- test/adapters/redis_test.rb | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/flipper/adapters/redis_cache_spec.rb b/spec/flipper/adapters/redis_cache_spec.rb index 3bfaf457e..0ed6536bd 100644 --- a/spec/flipper/adapters/redis_cache_spec.rb +++ b/spec/flipper/adapters/redis_cache_spec.rb @@ -14,7 +14,7 @@ } let(:memory_adapter) { Flipper::Adapters::Memory.new } - let(:cache) { Redis.new({url: ENV.fetch('BOXEN_REDIS_URL', 'localhost:6379')}) } + let(:cache) { Redis.new({url: ENV.fetch('BOXEN_REDIS_URL', 'redis://localhost:6379')}) } let(:adapter) { Flipper::Adapters::RedisCache.new(memory_adapter, cache) } let(:flipper) { Flipper.new(adapter) } diff --git a/test/adapters/redis_cache_test.rb b/test/adapters/redis_cache_test.rb index ec69a755f..e6e628d2b 100644 --- a/test/adapters/redis_cache_test.rb +++ b/test/adapters/redis_cache_test.rb @@ -6,7 +6,7 @@ class DalliTest < MiniTest::Test prepend Flipper::Test::SharedAdapterTests def setup - url = ENV.fetch('BOXEN_REDIS_URL', 'localhost:6379') + url = ENV.fetch('BOXEN_REDIS_URL', 'redis://localhost:6379') @cache = Redis.new({url: url}).tap { |c| c.flushdb } memory_adapter = Flipper::Adapters::Memory.new @adapter = Flipper::Adapters::RedisCache.new(memory_adapter, @cache) diff --git a/test/adapters/redis_test.rb b/test/adapters/redis_test.rb index ca3eb5811..5cc73fc9e 100644 --- a/test/adapters/redis_test.rb +++ b/test/adapters/redis_test.rb @@ -5,7 +5,7 @@ class RedisTest < MiniTest::Test prepend Flipper::Test::SharedAdapterTests def setup - url = ENV.fetch('BOXEN_REDIS_URL', 'localhost:6379') + url = ENV.fetch('BOXEN_REDIS_URL', 'redis://localhost:6379') client = Redis.new({url: url}).tap { |c| c.flushdb } @adapter = Flipper::Adapters::Redis.new(client) end