db-charmer 1.6.19 → 1.7.0.pre1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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