Module: DataFabric
- Defined in:
- lib/data_fabric.rb,
lib/data_fabric/ar20.rb,
lib/data_fabric/ar22.rb,
lib/data_fabric/version.rb
Overview
DataFabric adds a new level of flexibility to ActiveRecord connection handling. You need to describe the topology for your database infrastructure in your model(s). As with ActiveRecord normally, different models can use different topologies.
class MyHugeVolumeOfDataModel < ActiveRecord::Base
data_fabric :replicated => true, :shard_by => :city
end
There are four supported modes of operation, depending on the options given to the data_fabric method. The plugin will look for connections in your config/database.yml with the following convention:
No connection topology: #environment - this is the default, as with ActiveRecord, e.g. “production”
data_fabric :replicated => true #environment_#role - no sharding, just replication, where role is “master” or “slave”, e.g. “production_master”
data_fabric :shard_by => :city #group_#shard_#environment - sharding, no replication, e.g. “city_austin_production”
data_fabric :replicated => true, :shard_by => :city #group_#shard_#environment_#role - sharding with replication, e.g. “city_austin_production_master”
When marked as replicated, all write and transactional operations for the model go to the master, whereas read operations go to the slave.
Since sharding is an application-level concern, your application must set the shard to use based on the current request or environment. The current shard for a group is set on a thread local variable. For example, you can set the shard in an ActionController around_filter based on the user as follows:
class ApplicationController < ActionController::Base
around_filter :select_shard
private
def select_shard(&action_block)
DataFabric.activate_shard(:city => @current_user.city, &action_block)
end
end
Defined Under Namespace
Modules: ActiveRecordConnectionMethods, Extensions, Version Classes: ConnectionProxy, StringProxy
Class Method Summary collapse
- .activate_shard(shards, &block) ⇒ Object
- .active_shard(group) ⇒ Object
-
.deactivate_shard(shards) ⇒ Object
For cases where you can’t pass a block to activate_shards, you can clean up the thread local settings by calling this method at the end of processing.
- .ensure_setup ⇒ Object
- .init ⇒ Object
- .log(level = Logger::INFO, &block) ⇒ Object
- .shard_active_for?(group) ⇒ Boolean
Class Method Details
.activate_shard(shards, &block) ⇒ Object
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
# File 'lib/data_fabric.rb', line 57 def self.activate_shard(shards, &block) ensure_setup # Save the old shard settings to handle nested activation old = Thread.current[:shards].dup shards.each_pair do |key, value| Thread.current[:shards][key.to_s] = value.to_s end if block_given? begin yield ensure Thread.current[:shards] = old end end end |
.active_shard(group) ⇒ Object
85 86 87 88 89 90 91 |
# File 'lib/data_fabric.rb', line 85 def self.active_shard(group) raise ArgumentError, 'No shard has been activated' unless Thread.current[:shards] returning(Thread.current[:shards][group.to_s]) do |shard| raise ArgumentError, "No active shard for #{group}" unless shard end end |
.deactivate_shard(shards) ⇒ Object
For cases where you can’t pass a block to activate_shards, you can clean up the thread local settings by calling this method at the end of processing
78 79 80 81 82 83 |
# File 'lib/data_fabric.rb', line 78 def self.deactivate_shard(shards) ensure_setup shards.each do |key, value| Thread.current[:shards].delete(key.to_s) end end |
.ensure_setup ⇒ Object
98 99 100 |
# File 'lib/data_fabric.rb', line 98 def self.ensure_setup Thread.current[:shards] = {} unless Thread.current[:shards] end |
.init ⇒ Object
45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/data_fabric.rb', line 45 def self.init logger = ActiveRecord::Base.logger unless logger log { "Loading data_fabric #{DataFabric::Version::STRING} with ActiveRecord #{ActiveRecord::VERSION::STRING}" } if ActiveRecord::VERSION::STRING < '2.2.0' require 'data_fabric/ar20' else require 'data_fabric/ar22' end ActiveRecord::Base.send(:include, DataFabric::Extensions) end |
.log(level = Logger::INFO, &block) ⇒ Object
102 103 104 |
# File 'lib/data_fabric.rb', line 102 def self.log(level=Logger::INFO, &block) logger && logger.add(level, &block) end |
.shard_active_for?(group) ⇒ Boolean
93 94 95 96 |
# File 'lib/data_fabric.rb', line 93 def self.shard_active_for?(group) return true unless group Thread.current[:shards] and Thread.current[:shards][group.to_s] end |