From 7bc11a2a9534375c287807633e68b73f456aa133 Mon Sep 17 00:00:00 2001 From: Donal McBreen Date: Fri, 22 Sep 2023 16:10:34 +0100 Subject: [PATCH] Test cache without SolidCache.connects_to set --- .github/workflows/main.yml | 2 + README.md | 7 +- lib/solid_cache.rb | 4 +- lib/solid_cache/shards.rb | 6 +- lib/solid_cache/store/clusters.rb | 2 +- lib/solid_cache/store/entries.rb | 2 +- test/dummy/config/application.rb | 20 +- test/test_helper.rb | 2 +- test/unit/cluster_test.rb | 270 +++++++++++++------------- test/unit/connection_handling_test.rb | 60 ------ test/unit/instrumentation_test.rb | 62 ++++++ test/unit/solid_cache_test.rb | 6 +- test/unit/stats_test.rb | 25 ++- test/unit/trimming_test.rb | 74 +++---- 14 files changed, 287 insertions(+), 255 deletions(-) delete mode 100644 test/unit/connection_handling_test.rb create mode 100644 test/unit/instrumentation_test.rb diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 64c17c6..1b99864 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -43,3 +43,5 @@ jobs: bin/rails db:setup - name: Run tests run: bin/rails test + - name: Run tests (no connects-to) + run: NO_CONNECTS_TO=true bin/rails test diff --git a/README.md b/README.md index eac8946..421f87b 100644 --- a/README.md +++ b/README.md @@ -42,12 +42,11 @@ $ gem install solid_cache Adding the cache to your main database: ```bash -$ bin/rails solid_cache:install:migrations +$ bin/rails solid_cache:install ``` -Install and run migrations: +Then run migrations: ```bash -$ bin/rails solid_cache:install:migrations $ bin/rails db:migrate ``` @@ -82,7 +81,7 @@ Solid cache supports these options in addition to the universal `ActiveSupport:: - `max_age` - the maximum age of entries in the cache (default: `2.weeks.to_i`) - `max_entries` - the maximum number of entries allowed in the cache (default: `2.weeks.to_i`) - `cluster` - a Hash of options for the cache database cluster, e.g { shards: [:database1, :database2, :database3] } -- `clusters` - and Array of Hashes for separate cache clusters (ignored if `:cluster` is set) +- `clusters` - and Array of Hashes for multiple cache clusters (ignored if `:cluster` is set) - `active_record_instrumentation` - whether to instrument the cache's queries (default: `true`) For more information on cache clusters see [Sharding the cache](#sharding-the-cache) diff --git a/lib/solid_cache.rb b/lib/solid_cache.rb index 67fd9ac..466e218 100644 --- a/lib/solid_cache.rb +++ b/lib/solid_cache.rb @@ -10,7 +10,7 @@ module SolidCache mattr_accessor :executor, :connects_to def self.all_shard_keys - all_shards_config&.keys + all_shards_config&.keys || [ Record.default_shard ] end def self.all_shards_config @@ -20,7 +20,7 @@ def self.all_shards_config def self.each_shard return to_enum(:each_shard) unless block_given? - if (shards = connects_to[:shards]&.keys) + if (shards = connects_to && connects_to[:shards]&.keys) shards.each do |shard| Record.connected_to(shard: shard) { yield } end diff --git a/lib/solid_cache/shards.rb b/lib/solid_cache/shards.rb index 007d580..78dc60c 100644 --- a/lib/solid_cache/shards.rb +++ b/lib/solid_cache/shards.rb @@ -5,13 +5,17 @@ class Shards def initialize(options) case options when Array, NilClass - @names = options || SolidCache.all_shard_keys || [SolidCache::Record.default_shard] + @names = options || SolidCache.all_shard_keys @nodes = @names.to_h { |name| [ name, name ] } when Hash @names = options.keys @nodes = options.invert end + if (unknown_shards = names - SolidCache.all_shard_keys).any? + raise ArgumentError, "Unknown #{"shard".pluralize(unknown_shards)}: #{unknown_shards.join(", ")}" + end + @consistent_hash = MaglevHash.new(@nodes.keys) if sharded? end diff --git a/lib/solid_cache/store/clusters.rb b/lib/solid_cache/store/clusters.rb index 2c1a512..ad90f74 100644 --- a/lib/solid_cache/store/clusters.rb +++ b/lib/solid_cache/store/clusters.rb @@ -58,7 +58,7 @@ def writing_keys(entries, failsafe:, failsafe_returning: nil) sharded_entries.map do |shard, entries| failsafe(failsafe, returning: failsafe_returning) do cluster.with_shard(shard, async: async) do - yield cluster, shard, entries + yield cluster, entries end end end diff --git a/lib/solid_cache/store/entries.rb b/lib/solid_cache/store/entries.rb index 488813a..917b67a 100644 --- a/lib/solid_cache/store/entries.rb +++ b/lib/solid_cache/store/entries.rb @@ -41,7 +41,7 @@ def entry_write(key, payload) end def entry_write_multi(entries) - writing_keys(entries, failsafe: :write_multi_entries, failsafe_returning: false) do |cluster, shard, entries| + writing_keys(entries, failsafe: :write_multi_entries, failsafe_returning: false) do |cluster, entries| Entry.write_multi(entries) cluster.trim(entries.count) true diff --git a/test/dummy/config/application.rb b/test/dummy/config/application.rb index edb091a..334d1eb 100644 --- a/test/dummy/config/application.rb +++ b/test/dummy/config/application.rb @@ -24,15 +24,17 @@ class Application < Rails::Application # config.time_zone = "Central Time (US & Canada)" # config.eager_load_paths << Rails.root.join("extras") - config.solid_cache.connects_to = { - shards: { - default: { writing: :primary, reading: :primary_replica }, - default2: { writing: :primary_shard_one, reading: :primary_shard_one_replica }, - primary_shard_one: { writing: :primary_shard_one }, - primary_shard_two: { writing: :primary_shard_two }, - secondary_shard_one: { writing: :secondary_shard_one }, - secondary_shard_two: { writing: :secondary_shard_two } + unless ENV["NO_CONNECTS_TO"] + config.solid_cache.connects_to = { + shards: { + default: { writing: :primary, reading: :primary_replica }, + default2: { writing: :primary_shard_one, reading: :primary_shard_one_replica }, + primary_shard_one: { writing: :primary_shard_one }, + primary_shard_two: { writing: :primary_shard_two }, + secondary_shard_one: { writing: :secondary_shard_one }, + secondary_shard_two: { writing: :secondary_shard_two } + } } - } + end end end diff --git a/test/test_helper.rb b/test/test_helper.rb index 3142d0f..dab7cb2 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -18,7 +18,7 @@ def lookup_store(options = {}) store_options = { namespace: @namespace }.merge(options) - store_options.merge!(cluster: { shards: [:default, :default2] }) unless store_options.key?(:cluster) || store_options.key?(:clusters) + store_options.merge!(cluster: { shards: [:default] }) unless store_options.key?(:cluster) || store_options.key?(:clusters) ActiveSupport::Cache.lookup_store(:solid_cache_store, store_options) end diff --git a/test/unit/cluster_test.rb b/test/unit/cluster_test.rb index 6dba59f..249db1e 100644 --- a/test/unit/cluster_test.rb +++ b/test/unit/cluster_test.rb @@ -1,139 +1,141 @@ require "test_helper" class ClusterTest < ActiveSupport::TestCase - setup do - @cache = nil - @namespace = "test-#{SecureRandom.hex}" - primary_cluster = { shards: [:primary_shard_one, :primary_shard_two] } - secondary_cluster = { shards: [:secondary_shard_one, :secondary_shard_two] } - - @cache = lookup_store(expires_in: 60, clusters: [ primary_cluster, secondary_cluster ]) - @primary_cache = lookup_store(expires_in: 60, cluster: primary_cluster) - @secondary_cache = lookup_store(expires_in: 60, cluster: secondary_cluster) - end - - test "writes to both clusters" do - @cache.write("foo", 1) - sleep 0.1 - assert_equal 1, @cache.read("foo") - assert_equal 1, @primary_cache.read("foo") - assert_equal 1, @secondary_cache.read("foo") - end - - test "reads from primary cluster" do - @cache.write("foo", 1) - sleep 0.1 - assert_equal 1, @cache.read("foo") - - @secondary_cache.delete("foo") - assert_equal 1, @cache.read("foo") - - @primary_cache.delete("foo") - assert_nil @cache.read("foo") - end - - test "fetch writes to both clusters" do - @cache.fetch("foo") { 1 } - sleep 0.1 - - assert_equal 1, @cache.read("foo") - assert_equal 1, @primary_cache.read("foo") - assert_equal 1, @secondary_cache.read("foo") - end - - test "fetch reads from primary clusters" do - @cache.fetch("foo") { 1 } - sleep 0.1 - assert_equal 1, @cache.read("foo") - - @primary_cache.delete("foo") - @cache.fetch("foo") { 2 } - sleep 0.1 - - assert_equal 2, @cache.read("foo") - assert_equal 2, @primary_cache.read("foo") - assert_equal 2, @secondary_cache.read("foo") - - @secondary_cache.delete("foo") - assert_equal 2, @cache.fetch("foo") { 3 } - - assert_equal 2, @primary_cache.read("foo") - assert_nil @secondary_cache.read("foo") - end - - test "deletes from both cluster" do - @cache.write("foo", 1) - sleep 0.1 - assert_equal 1, @cache.read("foo") - - @cache.delete("foo") - sleep 0.1 - - assert_nil @cache.read("foo") - assert_nil @primary_cache.read("foo") - assert_nil @secondary_cache.read("foo") - end - - test "multi_writes to both clusters" do - values = { "foo" => "bar", "egg" => "spam" } - @cache.write_multi(values) - sleep 0.1 - assert_equal values, @cache.read_multi("foo", "egg") - assert_equal values, @primary_cache.read_multi("foo", "egg") - assert_equal values, @secondary_cache.read_multi("foo", "egg") - end - - test "delete_matched deletes from both caches" do - values = { "foo" => "bar", "baz" => "zab", "bab" => "dab" } - @cache.write_multi(values) - sleep 0.1 - - @cache.delete_matched("ba%") - sleep 0.1 - - assert_equal({ "foo" => "bar" }, @cache.read_multi(*values.keys)) - assert_equal({ "foo" => "bar" }, @primary_cache.read_multi(*values.keys)) - assert_equal({ "foo" => "bar" }, @secondary_cache.read_multi(*values.keys)) - end - - test "increment and decrement hit both clusters" do - @cache.write("foo", 1, raw: true) - sleep 0.1 - - assert_equal 1, @cache.read("foo", raw: true).to_i - assert_equal 1, @primary_cache.read("foo", raw: true).to_i - assert_equal 1, @secondary_cache.read("foo", raw: true).to_i - - @cache.increment("foo") - sleep 0.1 - - assert_equal 2, @cache.read("foo", raw: true).to_i - assert_equal 2, @primary_cache.read("foo", raw: true).to_i - assert_equal 2, @secondary_cache.read("foo", raw: true).to_i - - @secondary_cache.write("foo", 4, raw: true) - - @cache.decrement("foo") - sleep 0.1 - - assert_equal 1, @cache.read("foo", raw: true).to_i - assert_equal 1, @primary_cache.read("foo", raw: true).to_i - assert_equal 3, @secondary_cache.read("foo", raw: true).to_i - end - - test "cache with node names" do - @namespace = "test-#{SecureRandom.hex}" - primary_cluster = { shards: { primary_shard_one: :node1, primary_shard_two: :node2 } } - secondary_cluster = { shards: { primary_shard_one: :node3, primary_shard_two: :node4 } } - - @cache = lookup_store(expires_in: 60, clusters: [ primary_cluster, secondary_cluster ]) - @primary_cache = lookup_store(expires_in: 60, cluster: primary_cluster) - @secondary_cache = lookup_store(expires_in: 60, cluster: secondary_cluster) - - @cache.write("foo", 1) - sleep 0.1 - assert_equal 1, @cache.read("foo") - assert_equal 1, @primary_cache.read("foo") - assert_equal 1, @secondary_cache.read("foo") + unless ENV["NO_CONNECTS_TO"] + setup do + @cache = nil + @namespace = "test-#{SecureRandom.hex}" + primary_cluster = { shards: [:primary_shard_one, :primary_shard_two] } + secondary_cluster = { shards: [:secondary_shard_one, :secondary_shard_two] } + + @cache = lookup_store(expires_in: 60, clusters: [ primary_cluster, secondary_cluster ]) + @primary_cache = lookup_store(expires_in: 60, cluster: primary_cluster) + @secondary_cache = lookup_store(expires_in: 60, cluster: secondary_cluster) + end + + test "writes to both clusters" do + @cache.write("foo", 1) + sleep 0.1 + assert_equal 1, @cache.read("foo") + assert_equal 1, @primary_cache.read("foo") + assert_equal 1, @secondary_cache.read("foo") + end + + test "reads from primary cluster" do + @cache.write("foo", 1) + sleep 0.1 + assert_equal 1, @cache.read("foo") + + @secondary_cache.delete("foo") + assert_equal 1, @cache.read("foo") + + @primary_cache.delete("foo") + assert_nil @cache.read("foo") + end + + test "fetch writes to both clusters" do + @cache.fetch("foo") { 1 } + sleep 0.1 + + assert_equal 1, @cache.read("foo") + assert_equal 1, @primary_cache.read("foo") + assert_equal 1, @secondary_cache.read("foo") + end + + test "fetch reads from primary clusters" do + @cache.fetch("foo") { 1 } + sleep 0.1 + assert_equal 1, @cache.read("foo") + + @primary_cache.delete("foo") + @cache.fetch("foo") { 2 } + sleep 0.1 + + assert_equal 2, @cache.read("foo") + assert_equal 2, @primary_cache.read("foo") + assert_equal 2, @secondary_cache.read("foo") + + @secondary_cache.delete("foo") + assert_equal 2, @cache.fetch("foo") { 3 } + + assert_equal 2, @primary_cache.read("foo") + assert_nil @secondary_cache.read("foo") + end + + test "deletes from both cluster" do + @cache.write("foo", 1) + sleep 0.1 + assert_equal 1, @cache.read("foo") + + @cache.delete("foo") + sleep 0.1 + + assert_nil @cache.read("foo") + assert_nil @primary_cache.read("foo") + assert_nil @secondary_cache.read("foo") + end + + test "multi_writes to both clusters" do + values = { "foo" => "bar", "egg" => "spam" } + @cache.write_multi(values) + sleep 0.1 + assert_equal values, @cache.read_multi("foo", "egg") + assert_equal values, @primary_cache.read_multi("foo", "egg") + assert_equal values, @secondary_cache.read_multi("foo", "egg") + end + + test "delete_matched deletes from both caches" do + values = { "foo" => "bar", "baz" => "zab", "bab" => "dab" } + @cache.write_multi(values) + sleep 0.1 + + @cache.delete_matched("ba%") + sleep 0.1 + + assert_equal({ "foo" => "bar" }, @cache.read_multi(*values.keys)) + assert_equal({ "foo" => "bar" }, @primary_cache.read_multi(*values.keys)) + assert_equal({ "foo" => "bar" }, @secondary_cache.read_multi(*values.keys)) + end + + test "increment and decrement hit both clusters" do + @cache.write("foo", 1, raw: true) + sleep 0.1 + + assert_equal 1, @cache.read("foo", raw: true).to_i + assert_equal 1, @primary_cache.read("foo", raw: true).to_i + assert_equal 1, @secondary_cache.read("foo", raw: true).to_i + + @cache.increment("foo") + sleep 0.1 + + assert_equal 2, @cache.read("foo", raw: true).to_i + assert_equal 2, @primary_cache.read("foo", raw: true).to_i + assert_equal 2, @secondary_cache.read("foo", raw: true).to_i + + @secondary_cache.write("foo", 4, raw: true) + + @cache.decrement("foo") + sleep 0.1 + + assert_equal 1, @cache.read("foo", raw: true).to_i + assert_equal 1, @primary_cache.read("foo", raw: true).to_i + assert_equal 3, @secondary_cache.read("foo", raw: true).to_i + end + + test "cache with node names" do + @namespace = "test-#{SecureRandom.hex}" + primary_cluster = { shards: { primary_shard_one: :node1, primary_shard_two: :node2 } } + secondary_cluster = { shards: { primary_shard_one: :node3, primary_shard_two: :node4 } } + + @cache = lookup_store(expires_in: 60, clusters: [ primary_cluster, secondary_cluster ]) + @primary_cache = lookup_store(expires_in: 60, cluster: primary_cluster) + @secondary_cache = lookup_store(expires_in: 60, cluster: secondary_cluster) + + @cache.write("foo", 1) + sleep 0.1 + assert_equal 1, @cache.read("foo") + assert_equal 1, @primary_cache.read("foo") + assert_equal 1, @secondary_cache.read("foo") + end end end diff --git a/test/unit/connection_handling_test.rb b/test/unit/connection_handling_test.rb deleted file mode 100644 index 79c8ecd..0000000 --- a/test/unit/connection_handling_test.rb +++ /dev/null @@ -1,60 +0,0 @@ -require "test_helper" -require "active_support/testing/method_call_assertions" - -class SolidCache::TrimmingTest < ActiveSupport::TestCase - include ActiveSupport::Testing::TimeHelpers - - setup do - @namespace = "test-#{SecureRandom.hex}" - end - - def test_active_record_instrumention - instrumented_cache = lookup_store - uninstrumented_cache = lookup_store(active_record_instrumentation: false) - - calls = 0 - callback = ->(*args) { calls += 1 } - ActiveSupport::Notifications.subscribed(callback, "sql.active_record") do - assert_changes -> { calls } do - instrumented_cache.read("foo") - end - assert_changes -> { calls } do - instrumented_cache.write("foo", "bar") - end - assert_no_changes -> { calls } do - uninstrumented_cache.read("foo") - end - assert_no_changes -> { calls } do - uninstrumented_cache.write("foo", "bar") - end - end - end - - def test_no_connections_uninstrumented - ActiveRecord::ConnectionAdapters::ConnectionPool.any_instance.stubs(:connection).raises(ActiveRecord::StatementInvalid) - - cache = lookup_store(expires_in: 60, cluster: { shards: [:primary_shard_one, :primary_shard_two] }, active_record_instrumentation: false) - - assert_equal false, cache.write("1", "fsjhgkjfg") - assert_nil cache.read("1") - assert_nil cache.increment("1") - assert_nil cache.decrement("1") - assert_equal false, cache.delete("1") - assert_equal({}, cache.read_multi("1", "2", "3")) - assert_equal false, cache.write_multi("1" => "a", "2" => "b", "3" => "c") - end - - def test_no_connections_instrumented - ActiveRecord::ConnectionAdapters::ConnectionPool.any_instance.stubs(:connection).raises(ActiveRecord::StatementInvalid) - - cache = lookup_store(expires_in: 60, cluster: { shards: [:primary_shard_one, :primary_shard_two] }) - - assert_equal false, cache.write("1", "fsjhgkjfg") - assert_nil cache.read("1") - assert_nil cache.increment("1") - assert_nil cache.decrement("1") - assert_equal false, cache.delete("1") - assert_equal({}, cache.read_multi("1", "2", "3")) - assert_equal false, cache.write_multi("1" => "a", "2" => "b", "3" => "c") - end -end diff --git a/test/unit/instrumentation_test.rb b/test/unit/instrumentation_test.rb new file mode 100644 index 0000000..14f3b61 --- /dev/null +++ b/test/unit/instrumentation_test.rb @@ -0,0 +1,62 @@ +require "test_helper" +require "active_support/testing/method_call_assertions" + +class SolidCache::TrimmingTest < ActiveSupport::TestCase + include ActiveSupport::Testing::TimeHelpers + + setup do + @namespace = "test-#{SecureRandom.hex}" + end + + def test_active_record_instrumention + instrumented_cache = lookup_store + uninstrumented_cache = lookup_store(active_record_instrumentation: false) + + calls = 0 + callback = ->(*args) { calls += 1 } + ActiveSupport::Notifications.subscribed(callback, "sql.active_record") do + assert_changes -> { calls } do + instrumented_cache.read("foo") + end + assert_changes -> { calls } do + instrumented_cache.write("foo", "bar") + end + assert_no_changes -> { calls } do + uninstrumented_cache.read("foo") + end + assert_no_changes -> { calls } do + uninstrumented_cache.write("foo", "bar") + end + end + end + + unless ENV["NO_CONNECTS_TO"] + def test_no_connections_uninstrumented + ActiveRecord::ConnectionAdapters::ConnectionPool.any_instance.stubs(:connection).raises(ActiveRecord::StatementInvalid) + + cache = lookup_store(expires_in: 60, cluster: { shards: [:primary_shard_one, :primary_shard_two] }, active_record_instrumentation: false) + + assert_equal false, cache.write("1", "fsjhgkjfg") + assert_nil cache.read("1") + assert_nil cache.increment("1") + assert_nil cache.decrement("1") + assert_equal false, cache.delete("1") + assert_equal({}, cache.read_multi("1", "2", "3")) + assert_equal false, cache.write_multi("1" => "a", "2" => "b", "3" => "c") + end + + def test_no_connections_instrumented + ActiveRecord::ConnectionAdapters::ConnectionPool.any_instance.stubs(:connection).raises(ActiveRecord::StatementInvalid) + + cache = lookup_store(expires_in: 60, cluster: { shards: [:primary_shard_one, :primary_shard_two] }) + + assert_equal false, cache.write("1", "fsjhgkjfg") + assert_nil cache.read("1") + assert_nil cache.increment("1") + assert_nil cache.decrement("1") + assert_equal false, cache.delete("1") + assert_equal({}, cache.read_multi("1", "2", "3")) + assert_equal false, cache.write_multi("1" => "a", "2" => "b", "3" => "c") + end + end +end diff --git a/test/unit/solid_cache_test.rb b/test/unit/solid_cache_test.rb index e04b414..272a587 100644 --- a/test/unit/solid_cache_test.rb +++ b/test/unit/solid_cache_test.rb @@ -25,7 +25,11 @@ class SolidCacheTest < ActiveSupport::TestCase test "each_shard" do shards = SolidCache.each_shard.map { SolidCache::Record.current_shard } - assert_equal [ :default, :default2, :primary_shard_one, :primary_shard_two, :secondary_shard_one, :secondary_shard_two ], shards + if ENV["NO_CONNECTS_TO"] + assert_equal [ :default ], shards + else + assert_equal [ :default, :default2, :primary_shard_one, :primary_shard_two, :secondary_shard_one, :secondary_shard_two ], shards + end end end diff --git a/test/unit/stats_test.rb b/test/unit/stats_test.rb index e5f1c55..14f58ce 100644 --- a/test/unit/stats_test.rb +++ b/test/unit/stats_test.rb @@ -8,20 +8,35 @@ class SolidCache::StatsTest < ActiveSupport::TestCase @namespace = "test-#{SecureRandom.hex}" end - def test_stats - @cache = lookup_store(trim_batch_size: 2, max_age: 2.weeks.to_i, max_entries: 1000, shards: [:default, :default2]) + def test_stats_one_shard + @cache = lookup_store(trim_batch_size: 2, max_age: 2.weeks.to_i, max_entries: 1000, cluster: { shards: [ :default ] }) expected = { - shards: 2, + shards: 1, shards_stats: { - default: { max_age: 2.weeks.to_i, oldest_age: nil, max_entries: 1000, entries: 0 }, - default2: { max_age: 2.weeks.to_i, oldest_age: nil, max_entries: 1000, entries: 0 } + default: { max_age: 2.weeks.to_i, oldest_age: nil, max_entries: 1000, entries: 0 } } } assert_equal expected, @cache.stats end + unless ENV["NO_CONNECTS_TO"] + def test_stats_multiple_shards + @cache = lookup_store(trim_batch_size: 2, max_age: 2.weeks.to_i, max_entries: 1000, cluster: { shards: [:default, :default2] }) + + expected = { + shards: 2, + shards_stats: { + default: { max_age: 2.weeks.to_i, oldest_age: nil, max_entries: 1000, entries: 0 }, + default2: { max_age: 2.weeks.to_i, oldest_age: nil, max_entries: 1000, entries: 0 } + } + } + + assert_equal expected, @cache.stats + end + end + def test_stats_with_entries @cache = lookup_store(trim_batch_size: 2, max_age: 2.weeks.to_i, max_entries: 1000, cluster: { shards: [:default] }) diff --git a/test/unit/trimming_test.rb b/test/unit/trimming_test.rb index 907dc92..4cd8857 100644 --- a/test/unit/trimming_test.rb +++ b/test/unit/trimming_test.rb @@ -59,42 +59,44 @@ def test_trims_records_no_shards assert_equal 2, SolidCache::Entry.count end - def test_trims_old_records_multiple_shards - @cache = lookup_store(trim_batch_size: 2) - default_shard_keys, shard_one_keys = 20.times.map { |i| "key#{i}" }.partition { |key| @cache.primary_cluster.send(:shards).send(:shard_for, @cache.send(:normalize_key, key, {})) == :default } - - @cache.write(default_shard_keys[0], 1) - @cache.write(default_shard_keys[1], 2) - @cache.write(shard_one_keys[0], 3) - @cache.write(shard_one_keys[1], 4) - - assert_equal 1, @cache.read(default_shard_keys[0]) - assert_equal 2, @cache.read(default_shard_keys[1]) - assert_equal 3, @cache.read(shard_one_keys[0]) - assert_equal 4, @cache.read(shard_one_keys[1]) - - sleep 0.1 # ensure they are marked as read - send_entries_back_in_time(3.weeks) - - @cache.write(default_shard_keys[2], 5) - @cache.write(default_shard_keys[3], 6) - @cache.write(shard_one_keys[2], 7) - @cache.write(shard_one_keys[3], 8) - - sleep 0.1 - - assert_nil @cache.read(default_shard_keys[0]) - assert_nil @cache.read(default_shard_keys[1]) - assert_nil @cache.read(shard_one_keys[0]) - assert_nil @cache.read(shard_one_keys[1]) - assert_equal 5, @cache.read(default_shard_keys[2]) - assert_equal 6, @cache.read(default_shard_keys[3]) - assert_equal 7, @cache.read(shard_one_keys[2]) - assert_equal 8, @cache.read(shard_one_keys[3]) - - [:default, :default2].each do |shard| - SolidCache::Record.connected_to(shard: shard) do - assert_equal 2, SolidCache::Entry.count + unless ENV["NO_CONNECTS_TO"] + def test_trims_old_records_multiple_shards + @cache = lookup_store(trim_batch_size: 2, cluster: { shards: [:default, :default2] }) + default_shard_keys, shard_one_keys = 20.times.map { |i| "key#{i}" }.partition { |key| @cache.primary_cluster.send(:shards).send(:shard_for, @cache.send(:normalize_key, key, {})) == :default } + + @cache.write(default_shard_keys[0], 1) + @cache.write(default_shard_keys[1], 2) + @cache.write(shard_one_keys[0], 3) + @cache.write(shard_one_keys[1], 4) + + assert_equal 1, @cache.read(default_shard_keys[0]) + assert_equal 2, @cache.read(default_shard_keys[1]) + assert_equal 3, @cache.read(shard_one_keys[0]) + assert_equal 4, @cache.read(shard_one_keys[1]) + + sleep 0.1 # ensure they are marked as read + send_entries_back_in_time(3.weeks) + + @cache.write(default_shard_keys[2], 5) + @cache.write(default_shard_keys[3], 6) + @cache.write(shard_one_keys[2], 7) + @cache.write(shard_one_keys[3], 8) + + sleep 0.1 + + assert_nil @cache.read(default_shard_keys[0]) + assert_nil @cache.read(default_shard_keys[1]) + assert_nil @cache.read(shard_one_keys[0]) + assert_nil @cache.read(shard_one_keys[1]) + assert_equal 5, @cache.read(default_shard_keys[2]) + assert_equal 6, @cache.read(default_shard_keys[3]) + assert_equal 7, @cache.read(shard_one_keys[2]) + assert_equal 8, @cache.read(shard_one_keys[3]) + + [:default, :default2].each do |shard| + SolidCache::Record.connected_to(shard: shard) do + assert_equal 2, SolidCache::Entry.count + end end end end