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

Returns a new instance of ConnectionProxy.



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

def initialize(klass, options = {})
  @klass = klass
  @default_shard = DefaultShard.new(klass)
  @default_current_shard = @default_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



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/active_record/turntable/connection_proxy.rb', line 88

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

#default_current_shardObject (readonly)

Returns the value of attribute default_current_shard.



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

def default_current_shard
  @default_current_shard
end

#default_shardObject (readonly)

Returns the value of attribute default_shard.



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

def default_shard
  @default_shard
end

#klassObject (readonly)

Returns the value of attribute klass.



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

def klass
  @klass
end

#specObject



276
277
278
# File 'lib/active_record/turntable/connection_proxy.rb', line 276

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

Instance Method Details

#cacheObject



40
41
42
43
44
45
46
47
48
49
# File 'lib/active_record/turntable/connection_proxy.rb', line 40

def cache
  old = query_cache_enabled
  enable_query_cache!
  yield
ensure
  unless old
    disable_query_cache!
    clear_query_cache
  end
end

#clear_query_cacheObject



79
80
81
82
83
84
85
# File 'lib/active_record/turntable/connection_proxy.rb', line 79

def clear_query_cache
  default_connection.clear_query_cache

  cluster.shards.each do |shard|
    shard.connection.clear_query_cache
  end
end

#clear_query_cache_if_needed(method) ⇒ Object



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

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

#clusterObject



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

def cluster
  klass.turntable_cluster
end

#columns(*args) ⇒ Object



256
257
258
259
260
261
262
# File 'lib/active_record/turntable/connection_proxy.rb', line 256

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

#connectionObject

Returns connection of current shard.

Returns:

  • connection of current shard



144
145
146
# File 'lib/active_record/turntable/connection_proxy.rb', line 144

def connection
  current_shard.connection
end

#connection_poolObject

Returns connection_pool of current shard.

Returns:

  • connection_pool of current shard



149
150
151
# File 'lib/active_record/turntable/connection_proxy.rb', line 149

def connection_pool
  current_shard.connection_pool
end

#current_shardObject



134
135
136
# File 'lib/active_record/turntable/connection_proxy.rb', line 134

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

#current_shard=(shard) ⇒ Object



138
139
140
141
# File 'lib/active_record/turntable/connection_proxy.rb', line 138

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

#default_connectionObject



130
131
132
# File 'lib/active_record/turntable/connection_proxy.rb', line 130

def default_connection
  default_shard.connection
end

#disable_query_cache!Object



67
68
69
70
71
72
73
# File 'lib/active_record/turntable/connection_proxy.rb', line 67

def disable_query_cache!
  default_connection.disable_query_cache!

  cluster.shards.each do |shard|
    shard.connection.disable_query_cache!
  end
end

#enable_query_cache!Object



59
60
61
62
63
64
65
# File 'lib/active_record/turntable/connection_proxy.rb', line 59

def enable_query_cache!
  default_connection.enable_query_cache!

  cluster.shards.each do |shard|
    shard.connection.enable_query_cache!
  end
end

#fixed_shardObject



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

def fixed_shard
  fixed_shard_entry[object_id]
end

#fixed_shard=(shard) ⇒ Object



126
127
128
# File 'lib/active_record/turntable/connection_proxy.rb', line 126

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

#pk_and_sequence_for(*args) ⇒ Object



264
265
266
# File 'lib/active_record/turntable/connection_proxy.rb', line 264

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

#primary_key(*args) ⇒ Object



268
269
270
# File 'lib/active_record/turntable/connection_proxy.rb', line 268

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

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

rubocop:enable Style/MethodMissing

Returns:

  • (Boolean)


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

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

#shard_fixed?Boolean

Returns:

  • (Boolean)


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

def shard_fixed?
  !!fixed_shard
end

#shardsObject



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

def shards
  cluster.shards
end

#supports_views?(*args) ⇒ Boolean

Returns:

  • (Boolean)


272
273
274
# File 'lib/active_record/turntable/connection_proxy.rb', line 272

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

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



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

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

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



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

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

#uncachedObject



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

def uncached
  old = query_cache_enabled
  disable_query_cache!
  yield
ensure
  enable_query_cache! if old
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



201
202
203
204
205
206
207
208
209
210
211
212
213
214
# File 'lib/active_record/turntable/connection_proxy.rb', line 201

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

#with_default_and_all(continue_on_error = false) ⇒ Object

Send queries to default connection and all shards in this cluster

Parameters:

  • continue_on_error (Boolean) (defaults to: false)

    when a shard raises error, ignore exception and continue



218
219
220
221
222
223
224
225
226
227
228
229
230
231
# File 'lib/active_record/turntable/connection_proxy.rb', line 218

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

#with_default_shard(&block) ⇒ Object



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

def with_default_shard(&block)
  with_shard(default_shard) do
    yield
  end
end

#with_masterObject



183
184
185
186
187
188
189
# File 'lib/active_record/turntable/connection_proxy.rb', line 183

def with_master
  old = cluster.slave_enabled?
  cluster.set_slave_enabled(false)
  yield
ensure
  cluster.set_slave_enabled(old)
end

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



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

def with_recursive_shards(connection_name, *klasses, &block)
  with_shard(cluster.shard_registry[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



159
160
161
162
163
164
165
166
167
168
169
170
# File 'lib/active_record/turntable/connection_proxy.rb', line 159

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

#with_slaveObject



191
192
193
194
195
196
197
# File 'lib/active_record/turntable/connection_proxy.rb', line 191

def with_slave
  old = cluster.slave_enabled?
  cluster.set_slave_enabled(true)
  yield
ensure
  cluster.set_slave_enabled(old)
end