Class: ActiveRecord::Turntable::ConnectionProxy

Inherits:
Object
  • Object
show all
Includes:
Mixable
Defined in:
lib/active_record/turntable/connection_proxy.rb,
lib/active_record/turntable/connection_proxy/mixable.rb

Defined Under Namespace

Modules: Mixable

Constant Summary collapse

CLEAR_CACHE_METHODS =

for expiring query cache

[:update, :insert, :delete, :exec_insert, :exec_update, :exec_delete, :insert_many]

Constants included from Mixable

Mixable::EXCLUDE_QUERY_REGEXP, Mixable::METHODS_REGEXP, Mixable::QUERY_REGEXP

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Mixable

#mixable?

Constructor Details

#initialize(cluster, options = {}) ⇒ ConnectionProxy

Returns a new instance of ConnectionProxy.



11
12
13
14
15
16
# File 'lib/active_record/turntable/connection_proxy.rb', line 11

def initialize(cluster, options = {})
  @cluster      =  cluster
  @model_class  =  cluster.klass
  @default_current_shard =  (cluster.master || cluster.shards.first[1])
  @mixer = ActiveRecord::Turntable::Mixer.new(self)
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args, &block) ⇒ Object



54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/active_record/turntable/connection_proxy.rb', line 54

def method_missing(method, *args, &block)
  clear_query_cache_if_needed(method)
  if shard_fixed?
    connection.send(method, *args, &block)
  elsif mixable?(method, *args)
    fader = @mixer.build_fader(method, *args, &block)
    logger.debug { "[ActiveRecord::Turntable] Sending method: #{method}, " +
      "sql: #{args.first}, " +
      "shards: #{fader.shards_query_hash.keys.map(&:name)}" }
    fader.execute
  else
    connection.send(method, *args, &block)
  end
end

Instance Attribute Details

#specObject



230
231
232
# File 'lib/active_record/turntable/connection_proxy.rb', line 230

def spec
  @spec ||= master.connection_pool.spec
end

Instance Method Details

#cacheObject



31
32
33
34
35
36
# File 'lib/active_record/turntable/connection_proxy.rb', line 31

def cache
  enable_query_cache!
  yield
ensure
  clear_query_cache
end

#clear_query_cacheObject



48
49
50
51
52
# File 'lib/active_record/turntable/connection_proxy.rb', line 48

def clear_query_cache
  @model_class.turntable_connections.each do |k,v|
    v.connection.clear_query_cache
  end
end

#clear_query_cache_if_needed(method) ⇒ Object



44
45
46
# File 'lib/active_record/turntable/connection_proxy.rb', line 44

def clear_query_cache_if_needed(method)
  clear_query_cache if CLEAR_CACHE_METHODS.include?(method)
end

#clusterObject



73
74
75
# File 'lib/active_record/turntable/connection_proxy.rb', line 73

def cluster
  @cluster
end

#columns(*args) ⇒ Object



210
211
212
213
214
215
216
# File 'lib/active_record/turntable/connection_proxy.rb', line 210

def columns(*args)
  if args.size > 0
    master.connection_pool.columns[*args]
  else
    master.connection_pool.columns
  end
end

#connectionObject

Returns connection of current shard.

Returns:

  • connection of current shard



115
116
117
# File 'lib/active_record/turntable/connection_proxy.rb', line 115

def connection
  current_shard.connection
end

#connection_poolObject

Returns connection_pool of current shard.

Returns:

  • connection_pool of current shard



120
121
122
# File 'lib/active_record/turntable/connection_proxy.rb', line 120

def connection_pool
  current_shard.connection_pool
end

#current_shardObject



105
106
107
# File 'lib/active_record/turntable/connection_proxy.rb', line 105

def current_shard
  current_shard_entry[object_id] ||= @default_current_shard
end

#current_shard=(shard) ⇒ Object



109
110
111
112
# File 'lib/active_record/turntable/connection_proxy.rb', line 109

def current_shard=(shard)
  logger.debug { "Changing #{@model_class}'s shard to #{shard.name}"}
  current_shard_entry[object_id] = shard
end

#enable_query_cache!Object



38
39
40
41
42
# File 'lib/active_record/turntable/connection_proxy.rb', line 38

def enable_query_cache!
  @model_class.turntable_connections.each do |k,v|
    v.connection.enable_query_cache!
  end
end

#fixed_shardObject



85
86
87
# File 'lib/active_record/turntable/connection_proxy.rb', line 85

def fixed_shard
  fixed_shard_entry[object_id]
end

#fixed_shard=(shard) ⇒ Object



89
90
91
# File 'lib/active_record/turntable/connection_proxy.rb', line 89

def fixed_shard=(shard)
  fixed_shard_entry[object_id] = shard
end

#masterObject



93
94
95
# File 'lib/active_record/turntable/connection_proxy.rb', line 93

def master
  @cluster.master
end

#master_connectionObject



97
98
99
# File 'lib/active_record/turntable/connection_proxy.rb', line 97

def master_connection
  master.connection
end

#pk_and_sequence_for(*args) ⇒ Object



218
219
220
# File 'lib/active_record/turntable/connection_proxy.rb', line 218

def pk_and_sequence_for(*args)
  master.connection.send(:pk_and_sequence_for, *args)
end

#primary_key(*args) ⇒ Object



222
223
224
# File 'lib/active_record/turntable/connection_proxy.rb', line 222

def primary_key(*args)
  master.connection.send(:primary_key, *args)
end

#seqObject



101
102
103
# File 'lib/active_record/turntable/connection_proxy.rb', line 101

def seq
  @cluster.seq
end

#shard_fixed?Boolean

Returns:

  • (Boolean)


81
82
83
# File 'lib/active_record/turntable/connection_proxy.rb', line 81

def shard_fixed?
  !!fixed_shard
end

#shardsObject



77
78
79
# File 'lib/active_record/turntable/connection_proxy.rb', line 77

def shards
  @cluster.shards
end

#supports_views?(*args) ⇒ Boolean

Returns:

  • (Boolean)


226
227
228
# File 'lib/active_record/turntable/connection_proxy.rb', line 226

def supports_views?(*args)
  master.connection.send(:supports_views?, *args)
end

#to_sql(arel, binds = []) ⇒ Object



69
70
71
# File 'lib/active_record/turntable/connection_proxy.rb', line 69

def to_sql(arel, binds = [])
  master.connection.to_sql(arel, binds)
end

#transaction(options = {}, &block) ⇒ Object



27
28
29
# File 'lib/active_record/turntable/connection_proxy.rb', line 27

def transaction(options = {}, &block)
  connection.transaction(options, &block)
end

#with_all(continue_on_error = false) ⇒ Object

Send queries to all shards in this cluster

Parameters:

  • continue_on_error (Boolean) (defaults to: false)

    when a shard raises error, ignore exception and continue



155
156
157
158
159
160
161
162
163
164
165
166
167
168
# File 'lib/active_record/turntable/connection_proxy.rb', line 155

def with_all(continue_on_error = false)
  @cluster.shards.values.map do |shard|
    begin
      with_shard(shard) {
        yield
      }
    rescue Exception => err
      unless continue_on_error
        raise err
      end
      err
    end
  end
end

#with_master(&block) ⇒ Object



187
188
189
190
191
# File 'lib/active_record/turntable/connection_proxy.rb', line 187

def with_master(&block)
  with_shard(@cluster.master) do
    yield
  end
end

#with_master_and_all(continue_on_error = false) ⇒ Object

Send queries to master connection and all shards in this cluster

Parameters:

  • continue_on_error (Boolean) (defaults to: false)

    when a shard raises error, ignore exception and continue



172
173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'lib/active_record/turntable/connection_proxy.rb', line 172

def with_master_and_all(continue_on_error = false)
  ([@cluster.master] + @cluster.shards.values).map do |shard|
    begin
      with_shard(shard) {
        yield
      }
    rescue Exception => err
      unless continue_on_error
        raise err
      end
      err
    end
  end
end

#with_recursive_shards(connection_name, *klasses, &block) ⇒ Object



142
143
144
145
146
147
148
149
150
151
# File 'lib/active_record/turntable/connection_proxy.rb', line 142

def with_recursive_shards(connection_name, *klasses, &block)
  with_shard(shards[connection_name]) do
    if klasses.blank?
      yield
    else
      current_klass = klasses.shift
      current_klass.connection.with_recursive_shards(connection_name, *klasses, &block)
    end
  end
end

#with_shard(shard) ⇒ Object

Fix connection to given shard in block

Parameters:

  • shard (ActiveRecord::Base, Symbol, ActiveRecord::Turntable::Shard, Numeric, String)

    which you want to fix

  • shard (ActiveRecord::Base)

    AR Object

  • shard (Symbol)

    shard name symbol that defined in turntable.yml

  • shard (ActiveRecord::Turntable::Shard)

    Shard object

  • shard (String, Numeric)

    Raw sharding id



130
131
132
133
134
135
136
137
138
139
140
# File 'lib/active_record/turntable/connection_proxy.rb', line 130

def with_shard(shard)
  shard = cluster.to_shard(shard)

  old_shard, old_fixed = current_shard, fixed_shard
  self.current_shard = shard
  self.fixed_shard = shard
  yield
ensure
  self.fixed_shard = old_fixed
  self.current_shard = old_shard
end