Rails horizontal sharding doesn't connect in test environment

Viewed 127

I've implemented simple horizontal sharding in a rails application. There are 2 shards: Primary, and Archive.

The application works in production/dev/test when actually running, but when running the test suite, there is never a connection made to the archive shard.

I've set up a super simple test in a global setup in test_helper.rb to test this:

    ActiveRecord::Base.connected_to(shard: :primary, role: :reader) do
      p JobState.count
    end

    ActiveRecord::Base.connected_to(shard: :archive, role: :reader) do
      p JobState.count
    end

The output of which is

2 
No connection pool for 'ActiveRecord::Base' found for the 'archive' shard.

The databases exist, migrations run successfully. No problems with the configurations.

The confusing part is that running the actual application with RAILS_ENV=test rails s works just fine, as does RAILS_ENV=test rails console. I can run the exact queries without issue.

So there's definitely some sort of initialization not running for the test runner, but I don't know what it is.

I don't think it's the application configuration that's the problem, but I'll include that here too:

test:
  primary:
    <<: *default
    url: <%= ENV['TEST_DATABASE_URL'] %>
  archive:
    <<: *default
    url: <%= ENV['TEST_ARCHIVE_DATABASE_URL'] %>
class ApplicationRecord < RxModule::ApplicationRecord
  self.abstract_class = true
  connects_to shards: {
    primary: { writer: :primary, reader: :primary },
    archive: { writer: :archive, reader: :archive }
  }
end

Does anyone have any insight here?

1 Answers

I ended up finding the solution to this, but I feel I'm left with more questions than answers.

The problem was I was setting up the reading/writing roles as :reader and :writer in the connects_to statement in ApplicationRecord.

Rails expects these/defaults these to be :reading, and :writing. Changing the connect_to statement, as well as any connected_to statments throughout the application, fixed the entire issue, though I have no idea why it worked in all other contexts before that change.

Related