Repository: rails/solid_cache (Ruby)

Issue:
Issue with Multi-Shard Databases and Rails Database Selector in Read-Only Mode
When using multi-shard databases with the default Rails configuration for sharding, issues arise when attempting to write to the database while in read-only mode. The default configuration is as follows:
```ruby
Rails.application.configure do
  config.active_record.database_selector = { delay: 2.seconds }
  config.active_record.database_resolver = ActiveRecord::Middleware::DatabaseSelector::Resolver
  config.active_record.database_resolver_context = ActiveRecord::Middleware::DatabaseSelector::Resolver::Session
end
```
The issue occurs because, in read-only mode, the connection attempts to load the following class:
```ruby
SolidCache::Connections::Unmanaged.new
```
This leads to a failure since the connection persists in read-only mode, causing the operation to break when a write is attempted.

### Solution
To resolve this, I updated the configuration from using `database` to `databases`, and enclosed the database name in a single-element array within the `solid_cache.yml` file. This modification forces the system to load:
```ruby
SolidCache::Connections::Single.new(names.first)
```
By doing this, the issue was resolved, as it properly handles the connection in the correct mode.

### Before
Here’s the original `solid_cache.yml` configuration that caused the issue:
```yml
default: &default
  database: solid_cache
  store_options:
    max_age: <%= 1.week.to_i %>
    max_size: <%= 256.megabytes %>
    namespace: <%= Rails.env %>

development:
  <<: *default

test:
  <<: *default

production:
  <<: *default
```
### After
This is the updated `solid_cache.yml` configuration that resolved the issue:
```yml
default: &default
  databases: [solid_cache]
  store_options:
    max_age: <%= 1.week.to_i %>
    max_size: <%= 256.megabytes %>
    namespace: <%= Rails.env %>

development:
  <<: *default

test:
  <<: *default

production:
  <<: *default
```
Reference
You can find the specific lines in question that caused the issue here: https://github.com/rails/solid_cache/blob/main/lib/solid_cache/connections.rb#L5


Discussion:

Patch:
diff --git a/lib/solid_cache/configuration.rb b/lib/solid_cache/configuration.rb
index 99a1091f..17efbafc 100644
--- a/lib/solid_cache/configuration.rb
+++ b/lib/solid_cache/configuration.rb
@@ -35,7 +35,7 @@ def set_connects_to(database:, databases:, connects_to:)
         @connects_to =
           case
           when database
-            { database: { writing: database.to_sym } }
+            { shards: { database.to_sym => { writing: database.to_sym } } }
           when databases
             { shards: databases.map(&:to_sym).index_with { |database| { writing: database } } }
           when connects_to


Test patch:
diff --git a/test/models/solid_cache/record_test.rb b/test/models/solid_cache/record_test.rb
index 111255ac..02b52b09 100644
--- a/test/models/solid_cache/record_test.rb
+++ b/test/models/solid_cache/record_test.rb
@@ -4,7 +4,7 @@
 
 module SolidCache
   class RecordTest < ActiveSupport::TestCase
-    SINGLE_DB_CONFIGS = [ "config/solid_cache_no_database.yml", "config/solid_cache_database.yml", "config/solid_cache_unprepared_statements.yml" ]
+    SINGLE_DB_CONFIGS = [ "config/solid_cache_database.yml", "config/solid_cache_unprepared_statements.yml" ]
     MULTI_DB_CONFIGS = [
       "config/solid_cache_connects_to.yml",
       "config/solid_cache_encrypted.yml",
@@ -16,8 +16,12 @@ class RecordTest < ActiveSupport::TestCase
     test "each_shard" do
       shards = SolidCache::Record.each_shard.map { SolidCache::Record.current_shard }
       case ENV["SOLID_CACHE_CONFIG"]
-      when *SINGLE_DB_CONFIGS
+      when "config/solid_cache_no_database.yml"
         assert_equal [ :default ], shards
+      when "config/solid_cache_database.yml"
+        assert_equal [ :primary ], shards
+      when "config/solid_cache_unprepared_statements.yml"
+        assert_equal [ :primary_unprepared_statements ], shards
       when *MULTI_DB_CONFIGS
         assert_equal [ :primary_shard_one, :primary_shard_two, :secondary_shard_one, :secondary_shard_two ], shards
       else
@@ -28,8 +32,10 @@ class RecordTest < ActiveSupport::TestCase
     test "each_shard uses the default role" do
       role = ActiveRecord::Base.connected_to(role: :reading) { SolidCache::Record.each_shard.map { SolidCache::Record.current_role } }
       case ENV["SOLID_CACHE_CONFIG"]
-      when *SINGLE_DB_CONFIGS
+      when "config/solid_cache_no_database.yml"
         assert_equal [ :reading ], role
+      when *SINGLE_DB_CONFIGS
+        assert_equal [ :writing ], role
       when *MULTI_DB_CONFIGS
         assert_equal [ :writing, :writing, :writing, :writing ], role
       else
diff --git a/test/test_helper.rb b/test/test_helper.rb
index 70ee5a7f..3eba597c 100644
--- a/test/test_helper.rb
+++ b/test/test_helper.rb
@@ -74,7 +74,7 @@ def uncached_entry_count
   end
 
   def first_shard_key
-    single_database? ? :default : SolidCache.configuration.shard_keys.first
+    default_database? ? :default : SolidCache.configuration.shard_keys.first
   end
 
   def second_shard_key
@@ -85,6 +85,10 @@ def single_database?
     [ "config/solid_cache_database.yml", "config/solid_cache_no_database.yml", "config/solid_cache_unprepared_statements.yml" ].include?(ENV["SOLID_CACHE_CONFIG"])
   end
 
+  def default_database?
+    ENV["SOLID_CACHE_CONFIG"] == "config/solid_cache_no_database.yml"
+  end
+
   def shard_keys(cache, shard)
     namespaced_keys = 100.times.map { |i| @cache.send(:normalize_key, "key#{i}", {}) }
     shard_keys = cache.send(:connections).assign(namespaced_keys)[shard]
diff --git a/test/unit/expiry_test.rb b/test/unit/expiry_test.rb
index e71648a0..40020e56 100644
--- a/test/unit/expiry_test.rb
+++ b/test/unit/expiry_test.rb
@@ -9,7 +9,7 @@ class SolidCache::ExpiryTest < ActiveSupport::TestCase
 
   setup do
     @namespace = "test-#{SecureRandom.hex}"
-    @single_shard_cluster = single_database? ? {} : { shards: [ first_shard_key ] }
+    @single_shard_cluster = default_database? ? {} : { shards: [ first_shard_key ] }
   end
 
   teardown do