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].freeze

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(klass, cluster, options = {}) ⇒ ConnectionProxy



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

def initialize(klass, cluster, options = {})
  @klass   = klass
  @cluster = cluster
  @master_shard = MasterShard.new(klass)
  @default_current_shard = @master_shard
  @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

rubocop:disable Style/MethodMissing



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/active_record/turntable/connection_proxy.rb', line 57

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

#clusterObject (readonly)

Returns the value of attribute cluster.



83
84
85
# File 'lib/active_record/turntable/connection_proxy.rb', line 83

def cluster
  @cluster
end

#klassObject (readonly)

Returns the value of attribute klass.



9
10
11
# File 'lib/active_record/turntable/connection_proxy.rb', line 9

def klass
  @klass
end

#specObject



239
240
241
# File 'lib/active_record/turntable/connection_proxy.rb', line 239

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

Instance Method Details

#cacheObject



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

def cache
  enable_query_cache!
  yield
ensure
  clear_query_cache
end

#clear_query_cacheObject



50
51
52
53
54
# File 'lib/active_record/turntable/connection_proxy.rb', line 50

def clear_query_cache
  klass.turntable_connections.each do |_k, v|
    v.connection.clear_query_cache
  end
end

#clear_query_cache_if_needed(method) ⇒ Object



46
47
48
# File 'lib/active_record/turntable/connection_proxy.rb', line 46

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

#columns(*args) ⇒ Object



219
220
221
222
223
224
225
# File 'lib/active_record/turntable/connection_proxy.rb', line 219

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

#connectionObject



123
124
125
# File 'lib/active_record/turntable/connection_proxy.rb', line 123

def connection
  current_shard.connection
end

#connection_poolObject



128
129
130
# File 'lib/active_record/turntable/connection_proxy.rb', line 128

def connection_pool
  current_shard.connection_pool
end

#current_shardObject



113
114
115
# File 'lib/active_record/turntable/connection_proxy.rb', line 113

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

#current_shard=(shard) ⇒ Object



117
118
119
120
# File 'lib/active_record/turntable/connection_proxy.rb', line 117

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

#enable_query_cache!Object



40
41
42
43
44
# File 'lib/active_record/turntable/connection_proxy.rb', line 40

def enable_query_cache!
  klass.turntable_connections.each do |_k, v|
    v.connection.enable_query_cache!
  end
end

#fixed_shardObject



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

def fixed_shard
  fixed_shard_entry[object_id]
end

#fixed_shard=(shard) ⇒ Object



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

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

#masterObject



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

def master
  @master_shard
end

#master_connectionObject



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

def master_connection
  master.connection
end

#pk_and_sequence_for(*args) ⇒ Object



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

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

#primary_key(*args) ⇒ Object



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

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

#respond_to_missing?(method, include_private = false) ⇒ Boolean

rubocop:enable Style/MethodMissing



75
76
77
# File 'lib/active_record/turntable/connection_proxy.rb', line 75

def respond_to_missing?(method, include_private = false)
  connection.send(:respond_to?, method, include_private)
end

#seqObject



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

def seq
  @cluster.seq || master
end

#shard_fixed?Boolean



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

def shard_fixed?
  !!fixed_shard
end

#shardsObject



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

def shards
  @cluster.shards
end

#supports_views?(*args) ⇒ Boolean



235
236
237
# File 'lib/active_record/turntable/connection_proxy.rb', line 235

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

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



79
80
81
# File 'lib/active_record/turntable/connection_proxy.rb', line 79

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

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



29
30
31
# File 'lib/active_record/turntable/connection_proxy.rb', line 29

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

#with_all(continue_on_error = false) ⇒ Object

Send queries to all shards in this cluster



164
165
166
167
168
169
170
171
172
173
174
175
176
177
# File 'lib/active_record/turntable/connection_proxy.rb', line 164

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



196
197
198
199
200
# File 'lib/active_record/turntable/connection_proxy.rb', line 196

def with_master(&block)
  with_shard(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



181
182
183
184
185
186
187
188
189
190
191
192
193
194
# File 'lib/active_record/turntable/connection_proxy.rb', line 181

def with_master_and_all(continue_on_error = false)
  ([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



151
152
153
154
155
156
157
158
159
160
# File 'lib/active_record/turntable/connection_proxy.rb', line 151

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



138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/active_record/turntable/connection_proxy.rb', line 138

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

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