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

Returns a new instance of 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



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

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

#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



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

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

#clusterObject



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

def cluster
  @cluster
end

#columns(*args) ⇒ Object



216
217
218
219
220
221
222
# File 'lib/active_record/turntable/connection_proxy.rb', line 216

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



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

def connection
  current_shard.connection
end

#connection_poolObject

Returns connection_pool of current shard.

Returns:

  • connection_pool of current shard



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

def connection_pool
  current_shard.connection_pool
end

#current_shardObject



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

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

#current_shard=(shard) ⇒ Object



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

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



91
92
93
# File 'lib/active_record/turntable/connection_proxy.rb', line 91

def fixed_shard
  fixed_shard_entry[object_id]
end

#fixed_shard=(shard) ⇒ Object



95
96
97
# File 'lib/active_record/turntable/connection_proxy.rb', line 95

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

#masterObject



99
100
101
# File 'lib/active_record/turntable/connection_proxy.rb', line 99

def master
  @master_shard
end

#master_connectionObject



103
104
105
# File 'lib/active_record/turntable/connection_proxy.rb', line 103

def master_connection
  master.connection
end

#pk_and_sequence_for(*args) ⇒ Object



224
225
226
# File 'lib/active_record/turntable/connection_proxy.rb', line 224

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

#primary_key(*args) ⇒ Object



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

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

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

Returns:

  • (Boolean)


71
72
73
# File 'lib/active_record/turntable/connection_proxy.rb', line 71

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

#seqObject



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

def seq
  @cluster.seq || master
end

#shard_fixed?Boolean

Returns:

  • (Boolean)


87
88
89
# File 'lib/active_record/turntable/connection_proxy.rb', line 87

def shard_fixed?
  !!fixed_shard
end

#shardsObject



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

def shards
  @cluster.shards
end

#supports_views?(*args) ⇒ Boolean

Returns:

  • (Boolean)


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

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

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



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

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

Parameters:

  • continue_on_error (Boolean) (defaults to: false)

    when a shard raises error, ignore exception and continue



161
162
163
164
165
166
167
168
169
170
171
172
173
174
# File 'lib/active_record/turntable/connection_proxy.rb', line 161

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



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

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

Parameters:

  • continue_on_error (Boolean) (defaults to: false)

    when a shard raises error, ignore exception and continue



178
179
180
181
182
183
184
185
186
187
188
189
190
191
# File 'lib/active_record/turntable/connection_proxy.rb', line 178

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



148
149
150
151
152
153
154
155
156
157
# File 'lib/active_record/turntable/connection_proxy.rb', line 148

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



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

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