123456789_123456789_123456789_123456789_123456789_

Class: ActiveRecord::Middleware::ShardSelector

Relationships & Source Files
Inherits: Object
Defined in: activerecord/lib/active_record/middleware/shard_selector.rb

Overview

Shard Selector Middleware

The ShardSelector ::ActiveRecord::Middleware provides a framework for automatically swapping shards. Rails provides a basic framework to determine which shard to switch to and allows for applications to write custom strategies for swapping if needed.

The ShardSelector takes a set of options (currently only lock is supported) that can be used by the middleware to alter behavior. lock is true by default and will prohibit the request from switching shards once inside the block. If lock is false, then shard swapping will be allowed. For tenant based sharding, lock should always be true to prevent application code from mistakenly switching between tenants.

Options can be set in the config:

config.active_record.shard_selector = { lock: true }

Applications must also provide the code for the resolver as it depends on application specific models. An example resolver would look like this:

config.active_record.shard_resolver = ->(request) {
  subdomain = request.subdomain
  tenant = Tenant.find_by_subdomain!(subdomain)
  tenant.shard
}

Class Method Summary

Instance Attribute Summary

Instance Method Summary

Constructor Details

.new(app, resolver, options = {}) ⇒ ShardSelector

[ GitHub ]

  
# File 'activerecord/lib/active_record/middleware/shard_selector.rb', line 32

def initialize(app, resolver, options = {})
  @app = app
  @resolver = resolver
  @options = options
end

Instance Attribute Details

#options (readonly)

[ GitHub ]

  
# File 'activerecord/lib/active_record/middleware/shard_selector.rb', line 38

attr_reader :resolver, :options

#resolver (readonly)

[ GitHub ]

  
# File 'activerecord/lib/active_record/middleware/shard_selector.rb', line 38

attr_reader :resolver, :options

Instance Method Details

#call(env)

[ GitHub ]

  
# File 'activerecord/lib/active_record/middleware/shard_selector.rb', line 40

def call(env)
  request = ActionDispatch::Request.new(env)

  shard = selected_shard(request)

  set_shard(shard) do
    @app.call(env)
  end
end

#selected_shard(request) (private)

[ GitHub ]

  
# File 'activerecord/lib/active_record/middleware/shard_selector.rb', line 51

def selected_shard(request)
  resolver.call(request)
end

#set_shard(shard, &block) (private)

[ GitHub ]

  
# File 'activerecord/lib/active_record/middleware/shard_selector.rb', line 55

def set_shard(shard, &block)
  ActiveRecord::Base.connected_to(shard: shard.to_sym) do
    ActiveRecord::Base.prohibit_shard_swapping(options.fetch(:lock, true), &block)
  end
end