xbar 0.0.1 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Appraisals +25 -0
- data/README.mkdn +215 -0
- data/Rakefile +337 -1
- data/examples/README +5 -0
- data/examples/config/simple.json +22 -0
- data/examples/example1.rb +34 -0
- data/examples/migrations/1_create_users.rb +10 -0
- data/examples/setup.rb +43 -0
- data/gemfiles/rails3.gemfile +8 -0
- data/gemfiles/rails3.gemfile.lock +74 -0
- data/gemfiles/rails31.gemfile +8 -0
- data/gemfiles/rails31.gemfile.lock +83 -0
- data/gemfiles/rails32.gemfile +7 -0
- data/gemfiles/rails32.gemfile.lock +117 -0
- data/gemfiles/rails4.gemfile +9 -0
- data/gemfiles/rails4.gemfile.lock +134 -0
- data/lib/migrations/1_create_usage_statistics.rb +23 -0
- data/lib/xbar/association.rb +49 -0
- data/lib/xbar/association_collection.rb +69 -0
- data/lib/xbar/colors.rb +32 -0
- data/lib/xbar/has_and_belongs_to_many_association.rb +17 -0
- data/lib/xbar/logger.rb +14 -0
- data/lib/xbar/mapper.rb +304 -0
- data/lib/xbar/migration.rb +76 -0
- data/lib/xbar/model.rb +165 -0
- data/lib/xbar/proxy.rb +249 -0
- data/lib/xbar/rails2/association.rb +133 -0
- data/lib/xbar/rails2/persistence.rb +39 -0
- data/lib/xbar/rails3/arel.rb +13 -0
- data/lib/xbar/rails3/association.rb +112 -0
- data/lib/xbar/rails3/persistence.rb +37 -0
- data/lib/xbar/rails3.1/singular_association.rb +34 -0
- data/lib/xbar/scope_proxy.rb +55 -0
- data/lib/xbar/shard.rb +95 -0
- data/lib/xbar/version.rb +2 -2
- data/lib/xbar.rb +121 -2
- data/run +27 -0
- data/spec/config/acme.json +53 -0
- data/spec/config/connection.rb +2 -0
- data/spec/config/default.json +160 -0
- data/spec/config/duplicate_shard.json +21 -0
- data/spec/config/missing_key.json +20 -0
- data/spec/config/new_shards.json +29 -0
- data/spec/config/no_master_shard.json +19 -0
- data/spec/config/not_entire_sharded.json +23 -0
- data/spec/config/octopus.json +27 -0
- data/spec/config/octopus_rails.json +25 -0
- data/spec/config/production_fully_replicated.json +21 -0
- data/spec/config/production_raise_error.json +17 -0
- data/spec/config/simple.json +22 -0
- data/spec/config/single_adapter.json +20 -0
- data/spec/console.rb +15 -0
- data/spec/migrations/10_create_users_using_replication.rb +12 -0
- data/spec/migrations/11_add_field_in_all_slaves.rb +11 -0
- data/spec/migrations/12_create_users_using_block.rb +23 -0
- data/spec/migrations/13_create_users_using_block_and_using.rb +15 -0
- data/spec/migrations/1_create_users_on_master.rb +9 -0
- data/spec/migrations/2_create_users_on_canada.rb +11 -0
- data/spec/migrations/3_create_users_on_both_shards.rb +11 -0
- data/spec/migrations/4_create_users_on_shards_of_a_group.rb +11 -0
- data/spec/migrations/5_create_users_on_multiples_groups.rb +11 -0
- data/spec/migrations/6_raise_exception_with_invalid_shard_name.rb +11 -0
- data/spec/migrations/7_raise_exception_with_invalid_multiple_shard_names.rb +11 -0
- data/spec/migrations/8_raise_exception_with_invalid_group_name.rb +11 -0
- data/spec/migrations/9_raise_exception_with_multiple_invalid_group_names.rb +11 -0
- data/spec/spec_helper.rb +25 -0
- data/spec/support/database_models.rb +78 -0
- data/spec/support/xbar_helper.rb +42 -0
- data/spec/xbar/association_spec.rb +660 -0
- data/spec/xbar/controller_spec.rb +40 -0
- data/spec/xbar/logger_spec.rb +22 -0
- data/spec/xbar/mapper_spec.rb +283 -0
- data/spec/xbar/migration_spec.rb +110 -0
- data/spec/xbar/model_spec.rb +434 -0
- data/spec/xbar/proxy_spec.rb +124 -0
- data/spec/xbar/replication_spec.rb +94 -0
- data/spec/xbar/scope_proxy_spec.rb +22 -0
- data/spec/xbar/shard_spec.rb +36 -0
- data/xbar.gemspec +13 -3
- metadata +231 -10
data/lib/xbar/mapper.rb
ADDED
@@ -0,0 +1,304 @@
|
|
1
|
+
module XBar
|
2
|
+
#
|
3
|
+
# This module holds the current configuration. It is read from a JSON document
|
4
|
+
# and always represents exactly the state of that document. The configuration
|
5
|
+
# should not be 'tweaked' by changing the state of in-memory structures. The
|
6
|
+
# approved way to change the configuration is to call:
|
7
|
+
#
|
8
|
+
# XBar::Mapper.reset(:xbar_env => "<config file>",
|
9
|
+
# :app_env => "<application environment>")
|
10
|
+
#
|
11
|
+
# This loads a new configuration file from the XBar 'config' directory.
|
12
|
+
# This file may contain multiple 'environments'. Only the specified
|
13
|
+
# environment is used. Both arguments are required. Changes to the
|
14
|
+
# configuration via this API cause all Proxies and their Shards to be reset.
|
15
|
+
# This is, all Proxies are found and 'cleaned', and the Shard references held
|
16
|
+
# by each Proxy are dropped and new Shards are allocated.
|
17
|
+
#
|
18
|
+
# No thread-specific state is kept in the Mapper structure. In fact, the state
|
19
|
+
# it encapsulates is shared by all threads. In contrast, thread-specific
|
20
|
+
# state is kept in instances of the Proxy class, or instances of the Shard
|
21
|
+
# class. Thread specific state is handled as follows:
|
22
|
+
#
|
23
|
+
# Thread.current[:connection_proxy] references an instance of Proxy.
|
24
|
+
# In turn, an an instance of XBar::Proxy references a list of instances of
|
25
|
+
# XBar::Shard.
|
26
|
+
#
|
27
|
+
# Each Shard is considered to be an array of replicas, even if the
|
28
|
+
# configuration JSON specifies a single Connection (as a String literal). In
|
29
|
+
# this case, the Shard is an array of one replica. At any point in time, each
|
30
|
+
# Shard has one replica designated as the master. Thus the complete Shard
|
31
|
+
# description always an array of Connections and the first Connection in the
|
32
|
+
# array is considered to be the master.
|
33
|
+
#
|
34
|
+
# This module is included in the XBar::Proxy class. This adds instance
|
35
|
+
# methods to instances of XBar::Proxy that allow the configuration state to
|
36
|
+
# be read.
|
37
|
+
#
|
38
|
+
# The following data structures are maintained:
|
39
|
+
#
|
40
|
+
# @@connections -- a Hash, the key is the connection name and the value
|
41
|
+
# is a connection pool.
|
42
|
+
# @@shards -- an array of Hashes. For each hash the key is the shard name
|
43
|
+
# and the value is a connection pool.
|
44
|
+
#
|
45
|
+
module Mapper
|
46
|
+
|
47
|
+
def self.exports
|
48
|
+
# omit master_config
|
49
|
+
%w(connections shards adapters options app_env proxies).map(&:to_sym)
|
50
|
+
end
|
51
|
+
|
52
|
+
module ClassMethods
|
53
|
+
|
54
|
+
Mapper.exports.each do |var|
|
55
|
+
mattr_reader var
|
56
|
+
end
|
57
|
+
|
58
|
+
@@cached_config = nil
|
59
|
+
@@shards = HashWithIndifferentAccess.new
|
60
|
+
@@connections = HashWithIndifferentAccess.new
|
61
|
+
@@proxies = []
|
62
|
+
@@adapters = Set.new
|
63
|
+
@@config = nil
|
64
|
+
@@app_env = nil
|
65
|
+
@@xbar_env = nil
|
66
|
+
|
67
|
+
def config_file_name
|
68
|
+
file = "#{xbar_env}.json"
|
69
|
+
"#{XBar.directory}/config/#{file}"
|
70
|
+
end
|
71
|
+
|
72
|
+
def connection_file_name
|
73
|
+
file = "connection.rb"
|
74
|
+
"#{XBar.directory}/config/#{file}"
|
75
|
+
end
|
76
|
+
|
77
|
+
def config_from_file
|
78
|
+
file_name = config_file_name
|
79
|
+
puts "XBar::Mapper, reading configuration from file #{file_name}"
|
80
|
+
if File.exists? file_name
|
81
|
+
config = JSON.parse(ERB.new(File.read(file_name)).result)
|
82
|
+
else
|
83
|
+
config = {}
|
84
|
+
end
|
85
|
+
HashWithIndifferentAccess.new(config)
|
86
|
+
end
|
87
|
+
|
88
|
+
def config
|
89
|
+
@@cached_config ||= config_from_file
|
90
|
+
end
|
91
|
+
|
92
|
+
# Alter the configuration in-memory for the current XBar envirnoment.
|
93
|
+
def shards=(shards)
|
94
|
+
cached_config["environments"][app_env] = shards
|
95
|
+
end
|
96
|
+
|
97
|
+
# This needs to be reconciled with the 'environments' method in the
|
98
|
+
# XBar module. That method specifies the environments that XBar should
|
99
|
+
# be enabled for. The present method returns the environments that
|
100
|
+
# the current config file contains. XXX
|
101
|
+
def environments
|
102
|
+
config['environments'].keys
|
103
|
+
end
|
104
|
+
|
105
|
+
#
|
106
|
+
# When we switch the XBar env or the Rails env (either of which
|
107
|
+
# changes the set of available shards, we have to find all the
|
108
|
+
# connection proxies and reset their current shard to :master.)
|
109
|
+
#
|
110
|
+
# Q1. Are all the connection proxies pointed to by model classes
|
111
|
+
# findable through Thread.current[:connection_proxy]? We'll have
|
112
|
+
# to loop over all threads. XXX
|
113
|
+
#
|
114
|
+
# Alternatively, we can register each XBar::Proxy.new call to
|
115
|
+
# a hash in the XBar module.
|
116
|
+
#
|
117
|
+
def reset(options = {})
|
118
|
+
new_xbar_env = options[:xbar_env] || xbar_env
|
119
|
+
if (new_xbar_env != xbar_env) || (options[:clear_cache]) ||
|
120
|
+
(!@@cached_config.nil? && @@cached_config.empty?)
|
121
|
+
@@cached_config = nil
|
122
|
+
end
|
123
|
+
self.xbar_env = new_xbar_env
|
124
|
+
self.app_env = options[:app_env] if options[:app_env]
|
125
|
+
|
126
|
+
# puts "XBar::Mapper#reset, xbar_env=#{xbar_env}, app_env=#{app_env}"
|
127
|
+
initialize_shards(config)
|
128
|
+
initialize_options(config)
|
129
|
+
|
130
|
+
# If Rails or some other entity has not assigned a native connection
|
131
|
+
# for ActiveRecord, we will try to do something sensible. This is only
|
132
|
+
# needed if you have some enviroments for which XBar is not enabled.
|
133
|
+
# However, it's not likely you'll want to enable XBar for only some
|
134
|
+
# environments. (What would be a use case?) The first
|
135
|
+
# choice is that if we have a shard called 'master', we will use its
|
136
|
+
# connection specification. The second choice is to include a Ruby
|
137
|
+
# file that contains a call to 'establish connection'. In this case,
|
138
|
+
# we will create a shard called master with the same connection
|
139
|
+
# specification. Thus there will always be a 'master' shard.
|
140
|
+
#
|
141
|
+
# Also, there is the case where there is a connection, but the config
|
142
|
+
# document didn't specify a master shard.
|
143
|
+
|
144
|
+
begin
|
145
|
+
connection_pool = ActiveRecord::Base.connection_pool_without_xbar
|
146
|
+
rescue
|
147
|
+
if @@shards.keys.include? "master"
|
148
|
+
ActiveRecord::Base.establish_connection(
|
149
|
+
XBar::Mapper.shards[:master][0].spec.config)
|
150
|
+
else
|
151
|
+
# The config file didn't exist or didn't specify a master shard. Or
|
152
|
+
# app_env wasn't specified (as an argument option).
|
153
|
+
require connection_file_name
|
154
|
+
connection_pool = ActiveRecord::Base.connection_pool_without_xbar
|
155
|
+
end
|
156
|
+
end
|
157
|
+
if !@@shards.keys.include?("master") && connection_pool
|
158
|
+
@@shards[:master] = Array(connection_pool)
|
159
|
+
@@adapters << connection_pool.spec.config
|
160
|
+
end
|
161
|
+
|
162
|
+
@@proxies.each do |proxy|
|
163
|
+
proxy.reset_proxy
|
164
|
+
end
|
165
|
+
self
|
166
|
+
end
|
167
|
+
|
168
|
+
def initialize_options(aconfig)
|
169
|
+
@@options = aconfig["environments"][app_env].dup
|
170
|
+
@@options.delete("shards")
|
171
|
+
rescue
|
172
|
+
@@options = {}
|
173
|
+
ensure
|
174
|
+
@@options[:verify_connection] ||= false
|
175
|
+
end
|
176
|
+
|
177
|
+
def register(proxy)
|
178
|
+
@@proxies << proxy
|
179
|
+
|
180
|
+
# If we hang on to a reference to proxies here, the proxy will
|
181
|
+
# never be garbage collected, even when the thread that it was
|
182
|
+
# assigned to goes away. Find a way to fix this. XXX
|
183
|
+
end
|
184
|
+
|
185
|
+
def app_env
|
186
|
+
@@app_env = XBar.rails_env || @@app_env
|
187
|
+
end
|
188
|
+
|
189
|
+
def xbar_env
|
190
|
+
@env ||= 'default'
|
191
|
+
end
|
192
|
+
|
193
|
+
private
|
194
|
+
|
195
|
+
def app_env=(env)
|
196
|
+
if XBar.rails_env && XBar.rails_env != env
|
197
|
+
raise XBar::ConfigError, "Can't change app_env when you have a Rails environment."
|
198
|
+
end
|
199
|
+
@@app_env = env
|
200
|
+
end
|
201
|
+
|
202
|
+
# When XBar::Mapper is processing a reset, it will call this method. No other
|
203
|
+
# method should call this.
|
204
|
+
def xbar_env=(xbar_env)
|
205
|
+
@env = xbar_env
|
206
|
+
end
|
207
|
+
|
208
|
+
def initialize_shards(aconfig)
|
209
|
+
|
210
|
+
@@connections.clear
|
211
|
+
@@adapters.clear
|
212
|
+
@@shards.clear
|
213
|
+
|
214
|
+
if aconfig
|
215
|
+
begin
|
216
|
+
shards_config = aconfig["environments"][app_env]["shards"]
|
217
|
+
rescue
|
218
|
+
shards_config = nil
|
219
|
+
end
|
220
|
+
end
|
221
|
+
shards_config ||= []
|
222
|
+
shards_config.delete_if {|k| k == "__COMMENT"}
|
223
|
+
|
224
|
+
shards_config.each do |shard_key, connection_key|
|
225
|
+
if @@shards.include? shard_key
|
226
|
+
raise ConfigError, "You have duplicate shard names!"
|
227
|
+
end
|
228
|
+
if connection_key.kind_of? String
|
229
|
+
spec = aconfig["connections"][connection_key]
|
230
|
+
pool = install_connection(connection_key, spec)
|
231
|
+
@@shards[shard_key] = [pool]
|
232
|
+
else # an array of connection keys
|
233
|
+
@@shards[shard_key] = []
|
234
|
+
connection_key.each do |conn_key|
|
235
|
+
spec = aconfig["connections"][conn_key]
|
236
|
+
pool = install_connection(conn_key, spec)
|
237
|
+
@@shards[shard_key] << pool
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
241
|
+
# @@shards[:master] = [@@connections[:master]]
|
242
|
+
end
|
243
|
+
|
244
|
+
# Should return a ConnectionPool.
|
245
|
+
def install_connection(conn_key, spec)
|
246
|
+
unless spec
|
247
|
+
raise XBar::ConfigError, "No connection for key #{conn_key}"
|
248
|
+
end
|
249
|
+
if defined? ActiveRecord::Base::ConnectionSpecification::Resolver
|
250
|
+
resolver = ActiveRecord::Base::ConnectionSpecification::Resolver.new(spec, {})
|
251
|
+
spec = resolver.spec
|
252
|
+
@@adapters << spec.config[:adapter]
|
253
|
+
@@connections[conn_key.to_sym] =
|
254
|
+
ActiveRecord::ConnectionAdapters::ConnectionPool.new(spec)
|
255
|
+
else
|
256
|
+
old_install_connection(conn_key, spec)
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
def old_install_connection(conn_key, spec)
|
261
|
+
unless spec
|
262
|
+
raise XBar::ConfigError, "No connection for key #{conn_key}"
|
263
|
+
end
|
264
|
+
install_adapter(spec['adapter'])
|
265
|
+
@@connections[conn_key.to_sym] =
|
266
|
+
connection_pool_for(spec, "#{spec['adapter']}_connection")
|
267
|
+
end
|
268
|
+
|
269
|
+
# Called only from 'old_install_connection'. If you get here, you should not
|
270
|
+
# be using connection URI's.
|
271
|
+
def install_adapter(adapter)
|
272
|
+
@@adapters << adapter
|
273
|
+
begin
|
274
|
+
require "active_record/connection_adapters/#{adapter}_adapter"
|
275
|
+
rescue LoadError
|
276
|
+
raise "Please install the #{adapter} adapter: " +
|
277
|
+
"`gem install activerecord-#{adapter}-adapter` (#{$!})"
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
def connection_pool_for(adapter, spec)
|
282
|
+
ActiveRecord::ConnectionAdapters::ConnectionPool.new(
|
283
|
+
ActiveRecord::Base::ConnectionSpecification.new(adapter, spec))
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
# Give module XBar::Mapper the above class methods.
|
288
|
+
self.extend(ClassMethods)
|
289
|
+
|
290
|
+
Mapper.exports.each do |meth|
|
291
|
+
define_method(meth) {Mapper.send(meth)}
|
292
|
+
end
|
293
|
+
|
294
|
+
def reset_config(options = {})
|
295
|
+
Mapper.reset(options)
|
296
|
+
end
|
297
|
+
|
298
|
+
def register
|
299
|
+
Mapper.register(self)
|
300
|
+
end
|
301
|
+
|
302
|
+
end
|
303
|
+
|
304
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module XBar::Migration
|
2
|
+
|
3
|
+
def self.extended(base)
|
4
|
+
class << base
|
5
|
+
def announce_with_xbar(message)
|
6
|
+
announce_without_xbar("#{message} - #{get_current_shard}")
|
7
|
+
end
|
8
|
+
alias_method_chain :migrate, :xbar
|
9
|
+
alias_method_chain :announce, :xbar
|
10
|
+
attr_accessor :current_shard
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.included(base)
|
15
|
+
base.class_eval do
|
16
|
+
def announce_with_xbar(message)
|
17
|
+
announce_without_xbar("#{message} - #{get_current_shard}")
|
18
|
+
end
|
19
|
+
alias_method_chain :migrate, :xbar
|
20
|
+
alias_method_chain :announce, :xbar
|
21
|
+
attr_accessor :current_shard
|
22
|
+
end
|
23
|
+
base.extend(ClassMethods)
|
24
|
+
end
|
25
|
+
|
26
|
+
module ClassMethods
|
27
|
+
|
28
|
+
def using(*args)
|
29
|
+
if self.connection.is_a?(XBar::Proxy)
|
30
|
+
# Doesn't it make sense to only keep the schema_migrations table on the
|
31
|
+
# master shard? If we create these other tables, they are unused anyway.
|
32
|
+
#args.each do |shard|
|
33
|
+
# self.connection.check_schema_migrations(shard)
|
34
|
+
#end
|
35
|
+
@current_shard = *args
|
36
|
+
self.connection.enter_block_scope
|
37
|
+
self.current_shard = args
|
38
|
+
self.connection.current_shard = args
|
39
|
+
end
|
40
|
+
return self
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
def migrate_with_xbar(direction)
|
46
|
+
conn = ActiveRecord::Base.connection
|
47
|
+
raise "XBar::Migration#mismatched connections" unless conn == self.connection
|
48
|
+
if conn.kind_of?(XBar::Proxy)
|
49
|
+
u2 = self.class.instance_variable_get(:@current_shard)
|
50
|
+
conn.current_shard = u2 if u2
|
51
|
+
conn.send_queries_to_multiple_shards(conn.current_shard) do
|
52
|
+
migrate_without_xbar(direction)
|
53
|
+
end
|
54
|
+
else
|
55
|
+
migrate_without_xbar(direction)
|
56
|
+
end
|
57
|
+
ensure
|
58
|
+
if conn.kind_of?(XBar::Proxy)
|
59
|
+
conn.clean_proxy
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# Used by migration when printing out results.
|
64
|
+
def get_current_shard
|
65
|
+
if ActiveRecord::Base.connection.respond_to?(:current_shard)
|
66
|
+
"Shard: #{ActiveRecord::Base.connection.current_shard}"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
if XBar.rails31?
|
73
|
+
ActiveRecord::Migration.send :include, XBar::Migration
|
74
|
+
else
|
75
|
+
ActiveRecord::Migration.extend(XBar::Migration)
|
76
|
+
end
|
data/lib/xbar/model.rb
ADDED
@@ -0,0 +1,165 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
|
3
|
+
module XBar::Model
|
4
|
+
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
attr_accessor :current_shard
|
9
|
+
before_save :reload_connection
|
10
|
+
if XBar.rails3?
|
11
|
+
after_initialize :set_current_shard
|
12
|
+
else
|
13
|
+
def after_initialize
|
14
|
+
set_current_shard
|
15
|
+
end
|
16
|
+
end
|
17
|
+
class << self
|
18
|
+
alias_method_chain :connection, :xbar
|
19
|
+
alias_method_chain :connection_pool, :xbar
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def should_set_current_shard?
|
24
|
+
current_shard
|
25
|
+
end
|
26
|
+
|
27
|
+
def connection_proxy
|
28
|
+
self.class.connection_proxy
|
29
|
+
end
|
30
|
+
|
31
|
+
def reload_connection_safe
|
32
|
+
return yield unless should_set_current_shard?
|
33
|
+
original = connection_proxy.current_shard
|
34
|
+
connection_proxy.current_shard = current_shard
|
35
|
+
result = yield
|
36
|
+
connection_proxy.current_shard = original
|
37
|
+
result
|
38
|
+
end
|
39
|
+
|
40
|
+
def reload_connection
|
41
|
+
return unless should_set_current_shard?
|
42
|
+
connection_proxy.current_shard = current_shard
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
# After initialize callback.
|
48
|
+
def set_current_shard
|
49
|
+
if new_record? || connection_proxy.in_block_scope?
|
50
|
+
if XBar.debug
|
51
|
+
type = new_record? ? "New" : "Existing"
|
52
|
+
puts "#{type} model callback, current_shard=#{connection_proxy.current_shard}, " +
|
53
|
+
"block_scope=#{connection_proxy.in_block_scope?}"
|
54
|
+
end
|
55
|
+
self.current_shard = connection_proxy.current_shard
|
56
|
+
else
|
57
|
+
if XBar.debug
|
58
|
+
type = new_record? ? "New" : "Existing"
|
59
|
+
puts "#{type} model callback, current_shard=#{connection_proxy.current_shard} " +
|
60
|
+
"last_current_shard=#{connection_proxy.last_current_shard}, " +
|
61
|
+
"block_scope=#{connection_proxy.in_block_scope?}"
|
62
|
+
end
|
63
|
+
self.current_shard = connection_proxy.last_current_shard
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
module ClassMethods
|
68
|
+
|
69
|
+
def should_use_normal_connection?
|
70
|
+
(defined?(Rails) && XBar.config &&
|
71
|
+
!XBar.environments.include?(Rails.env.to_s)) ||
|
72
|
+
(if XBar.rails32?
|
73
|
+
_establish_connection
|
74
|
+
else
|
75
|
+
self.read_inheritable_attribute(:_establish_connection)
|
76
|
+
end
|
77
|
+
)
|
78
|
+
end
|
79
|
+
|
80
|
+
def connection_proxy
|
81
|
+
puts "Model allocating new connection proxy" unless Thread.current[:connection_proxy]
|
82
|
+
Thread.current[:connection_proxy] ||= XBar::Proxy.new
|
83
|
+
end
|
84
|
+
|
85
|
+
def connection_with_xbar
|
86
|
+
if should_use_normal_connection?
|
87
|
+
connection_without_xbar
|
88
|
+
else
|
89
|
+
#puts "Model connection with octopus" if XBar.debug
|
90
|
+
#if (connection_proxy.current_model.nil?) || (self != ActiveRecord::Base)
|
91
|
+
connection_proxy.current_model = self
|
92
|
+
#end
|
93
|
+
connection_proxy
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def connection_pool_with_xbar
|
98
|
+
if should_use_normal_connection?
|
99
|
+
connection_pool_without_xbar
|
100
|
+
else
|
101
|
+
connection_proxy.connection_pool
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def clean_table_name
|
106
|
+
return unless connection_proxy.should_clean_table_name?
|
107
|
+
if self != ActiveRecord::Base && self.respond_to?(:reset_table_name) &&
|
108
|
+
(if XBar.rails32?
|
109
|
+
!self._reset_table_name
|
110
|
+
else
|
111
|
+
!self.read_inheritable_attribute(:_reset_table_name)
|
112
|
+
end
|
113
|
+
)
|
114
|
+
self.reset_table_name
|
115
|
+
end
|
116
|
+
|
117
|
+
if XBar.rails3?
|
118
|
+
self.reset_column_information
|
119
|
+
self.instance_variable_set(:@quoted_table_name, nil)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def using(shard_name)
|
124
|
+
return self if defined?(::Rails) && !XBar.environments.include?(Rails.env.to_s)
|
125
|
+
clean_table_name
|
126
|
+
return XBar::ScopeProxy.new(shard_name, self)
|
127
|
+
end
|
128
|
+
|
129
|
+
def unreplicated_model
|
130
|
+
if XBar.rails32?
|
131
|
+
self._unreplicated = true
|
132
|
+
else
|
133
|
+
write_inheritable_attribute(:_unreplicated, true)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def unreplicated_model?
|
138
|
+
if XBar.rails32?
|
139
|
+
_unreplicated
|
140
|
+
else
|
141
|
+
read_inheritable_attribute(:_unreplicated)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def xbar_establish_connection(spec = nil)
|
146
|
+
if XBar.rails32?
|
147
|
+
self._establish_connection = true
|
148
|
+
else
|
149
|
+
write_inheritable_attribute(:_establish_connection, true)
|
150
|
+
end
|
151
|
+
establish_connection(spec)
|
152
|
+
end
|
153
|
+
|
154
|
+
def xbar_set_table_name(value = nil)
|
155
|
+
if XBar.rails32?
|
156
|
+
self._reset_table_name = true
|
157
|
+
self.table_name = value
|
158
|
+
else
|
159
|
+
write_inheritable_attribute(:_reset_table_name, true)
|
160
|
+
set_table_name(value)
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|