db-charmer 1.6.19 → 1.7.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (32) hide show
  1. data/CHANGES +14 -2
  2. data/README.rdoc +89 -4
  3. data/Rakefile +4 -0
  4. data/db-charmer.gemspec +17 -15
  5. data/lib/db_charmer.rb +34 -43
  6. data/lib/db_charmer/{abstract_adapter_extensions.rb → abstract_adapter/log_formatting.rb} +5 -3
  7. data/lib/db_charmer/action_controller/force_slave_reads.rb +65 -0
  8. data/lib/db_charmer/{association_preload.rb → active_record/association_preload.rb} +2 -2
  9. data/lib/db_charmer/{active_record_extensions.rb → active_record/class_attributes.rb} +19 -40
  10. data/lib/db_charmer/active_record/connection_switching.rb +77 -0
  11. data/lib/db_charmer/{db_magic.rb → active_record/db_magic.rb} +18 -8
  12. data/lib/db_charmer/active_record/finder_overrides.rb +61 -0
  13. data/lib/db_charmer/active_record/migration/multi_db_migrations.rb +71 -0
  14. data/lib/db_charmer/active_record/multi_db_proxy.rb +65 -0
  15. data/lib/db_charmer/active_record/named_scope/scope_proxy.rb +26 -0
  16. data/lib/db_charmer/active_record/sharding.rb +40 -0
  17. data/lib/db_charmer/connection_factory.rb +1 -1
  18. data/lib/db_charmer/core_extensions.rb +10 -0
  19. data/lib/db_charmer/force_slave_reads.rb +36 -0
  20. data/lib/db_charmer/sharding.rb +0 -36
  21. data/lib/db_charmer/sharding/method/db_block_group_map.rb +3 -3
  22. data/lib/db_charmer/sharding/method/db_block_map.rb +3 -3
  23. data/lib/db_charmer/sharding/stub_connection.rb +4 -4
  24. data/lib/db_charmer/version.rb +10 -0
  25. data/lib/tasks/databases.rake +6 -6
  26. metadata +28 -21
  27. data/VERSION +0 -1
  28. data/lib/db_charmer/connection_switch.rb +0 -40
  29. data/lib/db_charmer/finder_overrides.rb +0 -56
  30. data/lib/db_charmer/multi_db_migrations.rb +0 -67
  31. data/lib/db_charmer/multi_db_proxy.rb +0 -63
  32. data/lib/db_charmer/scope_proxy.rb +0 -22
@@ -0,0 +1,40 @@
1
+ module DbCharmer
2
+ module ActiveRecord
3
+ module Sharding
4
+
5
+ def self.extended(model)
6
+ model.cattr_accessor(:sharded_connection)
7
+ end
8
+
9
+ def shard_for(key, proxy_target = nil, &block)
10
+ raise ArgumentError, "No sharded connection configured!" unless sharded_connection
11
+ conn = sharded_connection.sharder.shard_for_key(key)
12
+ on_db(conn, proxy_target, &block)
13
+ end
14
+
15
+ # Run on default shard (if supported by the sharding method)
16
+ def on_default_shard(proxy_target = nil, &block)
17
+ raise ArgumentError, "No sharded connection configured!" unless sharded_connection
18
+
19
+ if sharded_connection.support_default_shard?
20
+ shard_for(:default, proxy_target, &block)
21
+ else
22
+ raise ArgumentError, "This model's sharding method does not support default shard"
23
+ end
24
+ end
25
+
26
+ # Enumerate shards
27
+ def on_each_shard(proxy_target = nil, &block)
28
+ raise ArgumentError, "No sharded connection configured!" unless sharded_connection
29
+
30
+ conns = sharded_connection.shard_connections
31
+ raise ArgumentError, "This model's sharding method does not support shards enumeration" unless conns
32
+
33
+ conns.each do |conn|
34
+ on_db(conn, proxy_target, &block)
35
+ end
36
+ end
37
+
38
+ end
39
+ end
40
+ end
@@ -62,7 +62,7 @@ module DbCharmer
62
62
 
63
63
  def self.generate_empty_abstract_ar_class(klass)
64
64
  # Define class
65
- module_eval "class #{klass} < ActiveRecord::Base; self.abstract_class = true; end"
65
+ module_eval "class #{klass} < ::ActiveRecord::Base; self.abstract_class = true; end"
66
66
 
67
67
  # Return class
68
68
  klass.constantize
@@ -4,6 +4,16 @@ class Object
4
4
  send(method, *options, &block)
5
5
  end
6
6
  end
7
+
8
+ # These methods are added to all objects so we could call proxy? on anything
9
+ # and figure if an object is a proxy w/o hitting method_missing or respond_to?
10
+ def self.proxy?
11
+ false
12
+ end
13
+
14
+ def proxy?
15
+ false
16
+ end
7
17
  end
8
18
 
9
19
  class NilClass
@@ -0,0 +1,36 @@
1
+ module DbCharmer
2
+ @@current_controller = nil
3
+ mattr_accessor :current_controller
4
+
5
+ @@forced_slave_reads = false
6
+
7
+ def self.force_slave_reads?
8
+ # If global force slave reads is requested, do it
9
+ return @@forced_slave_reads if @@forced_slave_reads
10
+
11
+ # If not, try to use current controller to decide on this
12
+ return false unless current_controller.respond_to?(:force_slave_reads?)
13
+
14
+ slave_reads = current_controller.force_slave_reads?
15
+ logger.debug("Using controller to figure out if slave reads should be forced: #{slave_reads}")
16
+ return slave_reads
17
+ end
18
+
19
+ def self.with_controller(controller)
20
+ raise ArgumentError, "No block given" unless block_given?
21
+ logger.debug("Setting current controller for db_charmer: #{controller.class.name}")
22
+ self.current_controller = controller
23
+ yield
24
+ ensure
25
+ logger.debug('Clearing current controller for db_charmer')
26
+ self.current_controller = nil
27
+ end
28
+
29
+ def self.force_slave_reads
30
+ raise ArgumentError, "No block given" unless block_given?
31
+ @@forced_slave_reads = true
32
+ yield
33
+ ensure
34
+ @@forced_slave_reads = false
35
+ end
36
+ end
@@ -1,41 +1,5 @@
1
1
  module DbCharmer
2
2
  module Sharding
3
- module ClassMethods
4
- def self.extended(model)
5
- model.cattr_accessor(:sharded_connection)
6
- end
7
-
8
- def shard_for(key, proxy_target = nil, &block)
9
- raise ArgumentError, "No sharded connection configured!" unless sharded_connection
10
- conn = sharded_connection.sharder.shard_for_key(key)
11
- on_db(conn, proxy_target, &block)
12
- end
13
-
14
- # Run on default shard (if supported by the sharding method)
15
- def on_default_shard(proxy_target = nil, &block)
16
- raise ArgumentError, "No sharded connection configured!" unless sharded_connection
17
-
18
- if sharded_connection.support_default_shard?
19
- shard_for(:default, proxy_target, &block)
20
- else
21
- raise ArgumentError, "This model's sharding method does not support default shard"
22
- end
23
- end
24
-
25
- # Enumerate shards
26
- def on_each_shard(proxy_target = nil, &block)
27
- raise ArgumentError, "No sharded connection configured!" unless sharded_connection
28
-
29
- conns = sharded_connection.shard_connections
30
- raise ArgumentError, "This model's sharding method does not support shards enumeration" unless conns
31
-
32
- conns.each do |conn|
33
- on_db(conn, proxy_target, &block)
34
- end
35
- end
36
- end
37
-
38
- #-------------------------------------------------------------
39
3
  @@sharded_connections = {}
40
4
 
41
5
  def self.register_connection(config)
@@ -10,7 +10,7 @@ module DbCharmer
10
10
  module Method
11
11
  class DbBlockGroupMap
12
12
  # Shard connection info model
13
- class Shard < ActiveRecord::Base
13
+ class Shard < ::ActiveRecord::Base
14
14
  validates_presence_of :db_host
15
15
  validates_presence_of :db_port
16
16
  validates_presence_of :db_user
@@ -21,7 +21,7 @@ module DbCharmer
21
21
  end
22
22
 
23
23
  # Table group info model
24
- class Group < ActiveRecord::Base
24
+ class Group < ::ActiveRecord::Base
25
25
  validates_presence_of :shard_id
26
26
  belongs_to :shard, :class_name => 'DbCharmer::Sharding::Method::DbBlockGroupMap::Shard'
27
27
  end
@@ -241,7 +241,7 @@ module DbCharmer
241
241
  def shard_connections
242
242
  # Find all groups
243
243
  prepare_shard_models
244
- groups = Group.all(:conditions => { :enabled => true })
244
+ groups = Group.all(:conditions => { :enabled => true }, :include => :shard)
245
245
  # Map them to shards
246
246
  groups.map { |group| shard_connection_config(group.shard, group.id) }
247
247
  end
@@ -42,7 +42,7 @@ module DbCharmer
42
42
  begin
43
43
  # Auto-allocate new blocks
44
44
  block ||= allocate_new_block_for_key(key)
45
- rescue ActiveRecord::StatementInvalid => e
45
+ rescue ::ActiveRecord::StatementInvalid => e
46
46
  raise unless e.message.include?('Duplicate entry')
47
47
  block = block_for_key(key)
48
48
  end
@@ -58,7 +58,7 @@ module DbCharmer
58
58
  shard_connection_config(shard_info)
59
59
  end
60
60
 
61
- class ShardInfo < ActiveRecord::Base
61
+ class ShardInfo < ::ActiveRecord::Base
62
62
  validates_presence_of :db_host
63
63
  validates_presence_of :db_port
64
64
  validates_presence_of :db_user
@@ -82,7 +82,7 @@ module DbCharmer
82
82
  sql = "SELECT * FROM #{map_table} WHERE start_id = #{key_range.first} AND end_id = #{key_range.last} LIMIT 1"
83
83
  connection.select_one(sql, 'Find a shard block')
84
84
  end
85
-
85
+
86
86
  set_cached_block(block_cache_key, block)
87
87
 
88
88
  return block
@@ -30,18 +30,18 @@ module DbCharmer
30
30
 
31
31
  # Get connection proxy for our real connection
32
32
  return nil unless conn
33
- @real_conn = ActiveRecord::Base.coerce_to_connection_proxy(conn, DbCharmer.connections_should_exist?)
33
+ @real_conn = ::ActiveRecord::Base.coerce_to_connection_proxy(conn, DbCharmer.connections_should_exist?)
34
34
  end
35
35
 
36
36
  def method_missing(meth, *args, &block)
37
37
  # Fail on database statements
38
- if ActiveRecord::ConnectionAdapters::DatabaseStatements.instance_methods.member?(meth.to_s)
39
- raise ActiveRecord::ConnectionNotEstablished, "You have to switch connection on your model before using it!"
38
+ if ::ActiveRecord::ConnectionAdapters::DatabaseStatements.instance_methods.member?(meth.to_s)
39
+ raise ::ActiveRecord::ConnectionNotEstablished, "You have to switch connection on your model before using it!"
40
40
  end
41
41
 
42
42
  # Fail if no connection has been established yet
43
43
  unless real_connection
44
- raise ActiveRecord::ConnectionNotEstablished, "No real connection to proxy this method to!"
44
+ raise ::ActiveRecord::ConnectionNotEstablished, "No real connection to proxy this method to!"
45
45
  end
46
46
 
47
47
  # Proxy the call to our real connection target
@@ -0,0 +1,10 @@
1
+ module DbCharmer
2
+ module Version
3
+ MAJOR = 1
4
+ MINOR = 7
5
+ PATCH = 0
6
+ BUILD = 'pre1'
7
+
8
+ STRING = [MAJOR, MINOR, PATCH, BUILD].compact.join('.')
9
+ end
10
+ end
@@ -2,7 +2,7 @@ namespace :db_charmer do
2
2
  namespace :create do
3
3
  desc 'Create all the local databases defined in config/database.yml'
4
4
  task :all => "db:load_config" do
5
- ActiveRecord::Base.configurations.each_value do |config|
5
+ ::ActiveRecord::Base.configurations.each_value do |config|
6
6
  # Skip entries that don't have a database key, such as the first entry here:
7
7
  #
8
8
  # defaults: &defaults
@@ -25,7 +25,7 @@ namespace :db_charmer do
25
25
  task :create => "db:load_config" do
26
26
  create_core_and_sub_database(ActiveRecord::Base.configurations[RAILS_ENV])
27
27
  end
28
-
28
+
29
29
  def create_core_and_sub_database(config)
30
30
  create_database(config)
31
31
  config.each_value do | sub_config |
@@ -34,11 +34,11 @@ namespace :db_charmer do
34
34
  create_database(sub_config)
35
35
  end
36
36
  end
37
-
37
+
38
38
  namespace :drop do
39
39
  desc 'Drops all the local databases defined in config/database.yml'
40
40
  task :all => "db:load_config" do
41
- ActiveRecord::Base.configurations.each_value do |config|
41
+ ::ActiveRecord::Base.configurations.each_value do |config|
42
42
  # Skip entries that don't have a database key
43
43
  next unless config['database']
44
44
  # Only connect to local databases
@@ -49,14 +49,14 @@ namespace :db_charmer do
49
49
 
50
50
  desc 'Drops the database for the current RAILS_ENV'
51
51
  task :drop => "db:load_config" do
52
- config = ActiveRecord::Base.configurations[RAILS_ENV || 'development']
52
+ config = ::ActiveRecord::Base.configurations[RAILS_ENV || 'development']
53
53
  begin
54
54
  drop_core_and_sub_database(config)
55
55
  rescue Exception => e
56
56
  puts "Couldn't drop #{config['database']} : #{e.inspect}"
57
57
  end
58
58
  end
59
-
59
+
60
60
 
61
61
  def local_database?(config, &block)
62
62
  if %w( 127.0.0.1 localhost ).include?(config['host']) || config['host'].blank?
metadata CHANGED
@@ -1,13 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: db-charmer
3
3
  version: !ruby/object:Gem::Version
4
- hash: 41
5
- prerelease: false
4
+ hash: 1923832059
5
+ prerelease: 6
6
6
  segments:
7
7
  - 1
8
- - 6
9
- - 19
10
- version: 1.6.19
8
+ - 7
9
+ - 0
10
+ - pre
11
+ - 1
12
+ version: 1.7.0.pre1
11
13
  platform: ruby
12
14
  authors:
13
15
  - Alexey Kovyrin
@@ -15,7 +17,7 @@ autorequire:
15
17
  bindir: bin
16
18
  cert_chain: []
17
19
 
18
- date: 2011-04-25 00:00:00 -04:00
20
+ date: 2011-05-16 00:00:00 -04:00
19
21
  default_executable:
20
22
  dependencies:
21
23
  - !ruby/object:Gem::Dependency
@@ -63,22 +65,24 @@ files:
63
65
  - Makefile
64
66
  - README.rdoc
65
67
  - Rakefile
66
- - VERSION
67
68
  - db-charmer.gemspec
68
69
  - init.rb
69
70
  - lib/db_charmer.rb
70
- - lib/db_charmer/abstract_adapter_extensions.rb
71
- - lib/db_charmer/active_record_extensions.rb
72
- - lib/db_charmer/association_preload.rb
71
+ - lib/db_charmer/abstract_adapter/log_formatting.rb
72
+ - lib/db_charmer/action_controller/force_slave_reads.rb
73
+ - lib/db_charmer/active_record/association_preload.rb
74
+ - lib/db_charmer/active_record/class_attributes.rb
75
+ - lib/db_charmer/active_record/connection_switching.rb
76
+ - lib/db_charmer/active_record/db_magic.rb
77
+ - lib/db_charmer/active_record/finder_overrides.rb
78
+ - lib/db_charmer/active_record/migration/multi_db_migrations.rb
79
+ - lib/db_charmer/active_record/multi_db_proxy.rb
80
+ - lib/db_charmer/active_record/named_scope/scope_proxy.rb
81
+ - lib/db_charmer/active_record/sharding.rb
73
82
  - lib/db_charmer/connection_factory.rb
74
83
  - lib/db_charmer/connection_proxy.rb
75
- - lib/db_charmer/connection_switch.rb
76
84
  - lib/db_charmer/core_extensions.rb
77
- - lib/db_charmer/db_magic.rb
78
- - lib/db_charmer/finder_overrides.rb
79
- - lib/db_charmer/multi_db_migrations.rb
80
- - lib/db_charmer/multi_db_proxy.rb
81
- - lib/db_charmer/scope_proxy.rb
85
+ - lib/db_charmer/force_slave_reads.rb
82
86
  - lib/db_charmer/sharding.rb
83
87
  - lib/db_charmer/sharding/connection.rb
84
88
  - lib/db_charmer/sharding/method/db_block_group_map.rb
@@ -86,6 +90,7 @@ files:
86
90
  - lib/db_charmer/sharding/method/hash_map.rb
87
91
  - lib/db_charmer/sharding/method/range.rb
88
92
  - lib/db_charmer/sharding/stub_connection.rb
93
+ - lib/db_charmer/version.rb
89
94
  - lib/tasks/databases.rake
90
95
  has_rdoc: true
91
96
  homepage: http://github.com/kovyrin/db-charmer
@@ -108,16 +113,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
108
113
  required_rubygems_version: !ruby/object:Gem::Requirement
109
114
  none: false
110
115
  requirements:
111
- - - ">="
116
+ - - ">"
112
117
  - !ruby/object:Gem::Version
113
- hash: 3
118
+ hash: 25
114
119
  segments:
115
- - 0
116
- version: "0"
120
+ - 1
121
+ - 3
122
+ - 1
123
+ version: 1.3.1
117
124
  requirements: []
118
125
 
119
126
  rubyforge_project:
120
- rubygems_version: 1.3.7
127
+ rubygems_version: 1.6.2
121
128
  signing_key:
122
129
  specification_version: 3
123
130
  summary: ActiveRecord Connections Magic
data/VERSION DELETED
@@ -1 +0,0 @@
1
- 1.6.19
@@ -1,40 +0,0 @@
1
- module DbCharmer
2
- module ConnectionSwitch
3
- module ClassMethods
4
- def coerce_to_connection_proxy(conn, should_exist = true)
5
- return nil if conn.nil?
6
-
7
- if conn.kind_of?(Symbol) || conn.kind_of?(String)
8
- return DbCharmer::ConnectionFactory.connect(conn, should_exist)
9
- end
10
-
11
- if conn.kind_of?(Hash)
12
- conn = conn.symbolize_keys
13
- raise ArgumentError, "Missing required :connection_name parameter" unless conn[:connection_name]
14
- return DbCharmer::ConnectionFactory.connect_to_db(conn[:connection_name], conn)
15
- end
16
-
17
- if conn.respond_to?(:db_charmer_connection_proxy)
18
- return conn.db_charmer_connection_proxy
19
- end
20
-
21
- if conn.kind_of?(ActiveRecord::ConnectionAdapters::AbstractAdapter) || conn.kind_of?(DbCharmer::Sharding::StubConnection)
22
- return conn
23
- end
24
-
25
- raise "Unsupported connection type: #{conn.class}"
26
- end
27
-
28
- def switch_connection_to(conn, require_config_to_exist = true)
29
- new_conn = coerce_to_connection_proxy(conn, require_config_to_exist)
30
-
31
- if db_charmer_connection_proxy.is_a?(DbCharmer::Sharding::StubConnection)
32
- db_charmer_connection_proxy.set_real_connection(new_conn)
33
- end
34
-
35
- self.db_charmer_connection_proxy = new_conn
36
- self.hijack_connection!
37
- end
38
- end
39
- end
40
- end
@@ -1,56 +0,0 @@
1
- module DbCharmer
2
- module FinderOverrides
3
- module ClassMethods
4
- SLAVE_METHODS = [ :find_by_sql, :count_by_sql, :calculate ]
5
- MASTER_METHODS = [ :update, :create, :delete, :destroy, :delete_all, :destroy_all, :update_all, :update_counters ]
6
-
7
- SLAVE_METHODS.each do |slave_method|
8
- class_eval <<-EOF, __FILE__, __LINE__ + 1
9
- def #{slave_method}(*args, &block)
10
- first_level_on_slave do
11
- super(*args, &block)
12
- end
13
- end
14
- EOF
15
- end
16
-
17
- MASTER_METHODS.each do |master_method|
18
- class_eval <<-EOF, __FILE__, __LINE__ + 1
19
- def #{master_method}(*args, &block)
20
- on_master do
21
- super(*args, &block)
22
- end
23
- end
24
- EOF
25
- end
26
-
27
- def find(*args, &block)
28
- options = args.last
29
- if options.is_a?(Hash) && options[:lock]
30
- on_master { super(*args, &block) }
31
- else
32
- super(*args, &block)
33
- end
34
- end
35
-
36
- private
37
-
38
- def first_level_on_slave
39
- if db_charmer_top_level_connection? && on_master.connection.open_transactions.zero?
40
- on_slave { yield }
41
- else
42
- yield
43
- end
44
- end
45
-
46
- end
47
-
48
- module InstanceMethods
49
- def reload(*args, &block)
50
- self.class.on_master do
51
- super(*args, &block)
52
- end
53
- end
54
- end
55
- end
56
- end