activerecord-turntable 3.0.0.alpha3 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. data/.gitmodules +3 -0
  3. data/.rubocop.yml +18 -0
  4. data/.rubocop_todo.yml +153 -0
  5. data/.travis.yml +20 -4
  6. data/CHANGELOG.md +32 -0
  7. data/Guardfile +2 -2
  8. data/README.md +68 -14
  9. data/Rakefile +42 -0
  10. data/activerecord-turntable.gemspec +13 -3
  11. data/gemfiles/rails_edge.gemfile +8 -0
  12. data/lib/active_record/turntable/active_record_ext/abstract_adapter.rb +3 -1
  13. data/lib/active_record/turntable/active_record_ext/activerecord_import_ext.rb +5 -7
  14. data/lib/active_record/turntable/active_record_ext/acts_as_archive_extension.rb +2 -2
  15. data/lib/active_record/turntable/active_record_ext/association.rb +3 -3
  16. data/lib/active_record/turntable/active_record_ext/clever_load.rb +2 -2
  17. data/lib/active_record/turntable/active_record_ext/database_tasks.rb +10 -8
  18. data/lib/active_record/turntable/active_record_ext/fixtures.rb +15 -13
  19. data/lib/active_record/turntable/active_record_ext/log_subscriber.rb +6 -0
  20. data/lib/active_record/turntable/active_record_ext/persistence.rb +25 -23
  21. data/lib/active_record/turntable/active_record_ext/schema_dumper.rb +8 -75
  22. data/lib/active_record/turntable/algorithm/range_algorithm.rb +6 -7
  23. data/lib/active_record/turntable/algorithm/range_bsearch_algorithm.rb +6 -7
  24. data/lib/active_record/turntable/base.rb +2 -17
  25. data/lib/active_record/turntable/cluster_helper_methods.rb +7 -4
  26. data/lib/active_record/turntable/connection_proxy.rb +4 -2
  27. data/lib/active_record/turntable/migration.rb +3 -5
  28. data/lib/active_record/turntable/mixer.rb +20 -19
  29. data/lib/active_record/turntable/pool_proxy.rb +20 -14
  30. data/lib/active_record/turntable/query_cache.rb +1 -1
  31. data/lib/active_record/turntable/railties/databases.rake +12 -12
  32. data/lib/active_record/turntable/seq_shard.rb +1 -1
  33. data/lib/active_record/turntable/sequencer/barrage.rb +3 -2
  34. data/lib/active_record/turntable/sequencer.rb +33 -29
  35. data/lib/active_record/turntable/shard.rb +8 -8
  36. data/lib/active_record/turntable/sharding_condition.rb +14 -14
  37. data/lib/active_record/turntable/sql_tree_patch.rb +7 -3
  38. data/lib/active_record/turntable/util.rb +4 -2
  39. data/lib/active_record/turntable/version.rb +1 -1
  40. data/lib/active_record/turntable.rb +6 -5
  41. data/lib/activerecord-turntable.rb +1 -0
  42. metadata +120 -101
  43. data/lib/active_record/turntable/helpers/test_helper.rb +0 -25
  44. data/lib/active_record/turntable/helpers.rb +0 -9
  45. data/spec/active_record/turntable/active_record_ext/association_preloader_spec.rb +0 -78
  46. data/spec/active_record/turntable/active_record_ext/association_spec.rb +0 -81
  47. data/spec/active_record/turntable/active_record_ext/clever_load_spec.rb +0 -72
  48. data/spec/active_record/turntable/active_record_ext/fixture_set_spec.rb +0 -27
  49. data/spec/active_record/turntable/active_record_ext/locking_optimistic_spec.rb +0 -28
  50. data/spec/active_record/turntable/active_record_ext/migration_spec.rb +0 -38
  51. data/spec/active_record/turntable/active_record_ext/persistence_spec.rb +0 -211
  52. data/spec/active_record/turntable/active_record_ext/sequencer_spec.rb +0 -22
  53. data/spec/active_record/turntable/active_record_ext/test_fixtures_spec.rb +0 -34
  54. data/spec/active_record/turntable/algorithm/modulo_algorithm_spec.rb +0 -34
  55. data/spec/active_record/turntable/algorithm/range_algorithm_spec.rb +0 -34
  56. data/spec/active_record/turntable/algorithm/range_bsearch_algorithm_spec.rb +0 -34
  57. data/spec/active_record/turntable/algorithm_spec.rb +0 -100
  58. data/spec/active_record/turntable/base_spec.rb +0 -13
  59. data/spec/active_record/turntable/cluster_spec.rb +0 -48
  60. data/spec/active_record/turntable/config_spec.rb +0 -17
  61. data/spec/active_record/turntable/connection_proxy_spec.rb +0 -252
  62. data/spec/active_record/turntable/finder_spec.rb +0 -40
  63. data/spec/active_record/turntable/mixer/fader_spec.rb +0 -4
  64. data/spec/active_record/turntable/mixer_spec.rb +0 -112
  65. data/spec/active_record/turntable/query_cache_spec.rb +0 -28
  66. data/spec/active_record/turntable/sequencer/api_spec.rb +0 -38
  67. data/spec/active_record/turntable/sequencer/barrage_spec.rb +0 -22
  68. data/spec/active_record/turntable/sequencer/mysql_spec.rb +0 -22
  69. data/spec/active_record/turntable/shard_spec.rb +0 -21
  70. data/spec/active_record/turntable/sql_tree_patch_spec.rb +0 -34
  71. data/spec/active_record/turntable/transaction_spec.rb +0 -35
  72. data/spec/active_record/turntable_spec.rb +0 -30
  73. data/spec/config/database.yml +0 -35
  74. data/spec/config/turntable.yml +0 -56
  75. data/spec/fabricators/.gitkeep +0 -0
  76. data/spec/fabricators/turntable_fabricator.rb +0 -12
  77. data/spec/fixtures/cards.yml +0 -11
  78. data/spec/migrations/.gitkeep +0 -0
  79. data/spec/migrations/001_create_users.rb +0 -17
  80. data/spec/migrations/002_create_user_statuses.rb +0 -16
  81. data/spec/migrations/003_create_cards.rb +0 -14
  82. data/spec/migrations/004_create_cards_users.rb +0 -15
  83. data/spec/models/card.rb +0 -3
  84. data/spec/models/cards_user.rb +0 -10
  85. data/spec/models/cards_users_histories.rb +0 -7
  86. data/spec/models/events_users_history.rb +0 -7
  87. data/spec/models/user.rb +0 -7
  88. data/spec/models/user_status.rb +0 -6
  89. data/spec/spec_helper.rb +0 -38
  90. data/spec/support/matchers/be_saved_to.rb +0 -6
  91. data/spec/support/turntable_helper.rb +0 -30
@@ -26,24 +26,30 @@ module ActiveRecord::Turntable
26
26
  end
27
27
  end
28
28
 
29
- %w(active_connection?).each do |name|
30
- define_method(name.to_sym) do |*_args|
31
- @proxy.master.connection_pool.send(name.to_sym) ||
32
- @proxy.seq.connection_pool.try(name.to_sym) if @proxy.respond_to?(:seq) ||
33
- @proxy.shards.values.any? do |pool|
34
- pool.connection_pool.send(name.to_sym)
35
- end
36
- end
29
+ def active_connection?
30
+ connection_pools_list.any?(&:active_connection?)
37
31
  end
38
32
 
39
- %w(disconnect! release_connection clear_all_connections! clear_active_connections! clear_reloadable_connections! clear_stale_cached_connections! verify_active_connections!).each do |name|
33
+ %w(disconnect!
34
+ release_connection
35
+ clear_all_connections!
36
+ clear_active_connections!
37
+ clear_reloadable_connections!
38
+ clear_stale_cached_connections!
39
+ verify_active_connections!).each do |name|
40
40
  define_method(name.to_sym) do
41
- @proxy.master.connection_pool.send(name.to_sym)
42
- @proxy.seq.connection_pool.try(name.to_sym) if @proxy.respond_to?(:seq)
43
- @proxy.shards.values.each do |pool|
44
- pool.connection_pool.send(name.to_sym)
45
- end
41
+ connection_pools_list.each { |cp| cp.public_send(name.to_sym) }
46
42
  end
47
43
  end
44
+
45
+ private
46
+
47
+ def connection_pools_list
48
+ pools = []
49
+ pools << proxy.master.connection_pool
50
+ pools << proxy.seq.try(:connection_pool) if proxy.respond_to?(:seq)
51
+ pools.concat(proxy.shards.values.map(&:connection_pool))
52
+ pools.compact
53
+ end
48
54
  end
49
55
  end
@@ -17,7 +17,7 @@ module ActiveRecord
17
17
  end
18
18
 
19
19
  def self.complete(enabled)
20
- klasses = ActiveRecord::Base.turntable_connections.values
20
+ klasses = ActiveRecord::Base.turntable_connections.values
21
21
  klasses.each do |k|
22
22
  k.connection.clear_query_cache
23
23
  k.connection.disable_query_cache! unless enabled
@@ -35,9 +35,9 @@ db_namespace = namespace :db do
35
35
  # TODO: implement schema:cache:xxxx
36
36
  task :dump do
37
37
  require "active_record/schema_dumper"
38
- config = ActiveRecord::Base.configurations[Rails.env]
39
- shard_configs = config["shards"]
40
- shard_configs.merge!(config["seq"]) if config["seq"]
38
+ current_config = ActiveRecord::Base.configurations[Rails.env]
39
+ shard_configs = current_config["shards"]
40
+ shard_configs.merge!(current_config["seq"]) if current_config["seq"]
41
41
  if shard_configs
42
42
  shard_configs.each do |name, config|
43
43
  next unless config["database"]
@@ -48,15 +48,15 @@ db_namespace = namespace :db do
48
48
  end
49
49
  end
50
50
  end
51
- ActiveRecord::Base.establish_connection(config)
51
+ ActiveRecord::Base.establish_connection(current_config)
52
52
  turntable_namespace["schema:dump"].reenable
53
53
  end
54
54
 
55
55
  desc "Load a schema.rb file into the database"
56
56
  task :load do
57
- config = ActiveRecord::Base.configurations[Rails.env]
58
- shard_configs = config["shards"]
59
- shard_configs.merge!(config["seq"]) if config["seq"]
57
+ current_config = ActiveRecord::Base.configurations[Rails.env]
58
+ shard_configs = current_config["shards"]
59
+ shard_configs.merge!(current_config["seq"]) if current_config["seq"]
60
60
  if shard_configs
61
61
  shard_configs.each do |name, config|
62
62
  next unless config["database"]
@@ -69,7 +69,7 @@ db_namespace = namespace :db do
69
69
  end
70
70
  end
71
71
  end
72
- ActiveRecord::Base.establish_connection(config)
72
+ ActiveRecord::Base.establish_connection(current_config)
73
73
  end
74
74
  end
75
75
 
@@ -116,16 +116,16 @@ db_namespace = namespace :db do
116
116
  namespace :test do
117
117
  # desc "Empty the test database"
118
118
  task :purge do
119
- config = ActiveRecord::Base.configurations[Rails.env]
120
- shard_configs = config["shards"]
121
- shard_configs.merge!(config["seq"]) if config["seq"]
119
+ current_config = ActiveRecord::Base.configurations[Rails.env]
120
+ shard_configs = current_config["shards"]
121
+ shard_configs.merge!(current_config["seq"]) if current_config["seq"]
122
122
  if shard_configs
123
123
  shard_configs.each do |_name, config|
124
124
  next unless config["database"]
125
125
  ActiveRecord::Tasks::DatabaseTasks.purge config
126
126
  end
127
127
  end
128
- ActiveRecord::Base.establish_connection(config)
128
+ ActiveRecord::Base.establish_connection(current_config)
129
129
  end
130
130
  end
131
131
  end
@@ -3,7 +3,7 @@ module ActiveRecord::Turntable
3
3
  private
4
4
 
5
5
  def create_connection_class
6
- klass = get_or_set_connection_class
6
+ klass = connection_class_instance
7
7
  klass.remove_connection
8
8
  klass.establish_connection ActiveRecord::Base.connection_pool.spec.config[:seq][name].with_indifferent_access
9
9
  klass
@@ -1,7 +1,8 @@
1
1
  module ActiveRecord::Turntable
2
2
  class Sequencer
3
3
  class Barrage < Sequencer
4
- @@unique_barrage_instance = {}
4
+ class_attribute :unique_barrage_instance
5
+ self.unique_barrage_instance = {}
5
6
 
6
7
  def initialize(klass, options = {})
7
8
  require "barrage"
@@ -20,7 +21,7 @@ module ActiveRecord::Turntable
20
21
  private
21
22
 
22
23
  def barrage
23
- @@unique_barrage_instance[@options] ||= ::Barrage.new(@options)
24
+ self.unique_barrage_instance[@options] ||= ::Barrage.new(@options)
24
25
  end
25
26
  end
26
27
  end
@@ -13,33 +13,48 @@ module ActiveRecord::Turntable
13
13
  autoload :Barrage
14
14
  end
15
15
 
16
- @@sequence_types = {
16
+ class_attribute :sequence_types
17
+ class_attribute :sequences
18
+ class_attribute :tables
19
+
20
+ self.sequence_types = {
17
21
  api: Api,
18
22
  mysql: Mysql,
19
23
  barrage: Barrage,
20
24
  }
25
+ self.sequences = {}
26
+ self.tables = {}
21
27
 
22
- @@sequences = {}
23
- @@tables = {}
24
- cattr_reader :sequences, :tables
28
+ class << self
29
+ def build(klass, sequence_name = nil, cluster_name = nil)
30
+ sequence_name ||= current_cluster_config_for(cluster_name || klass)[:seq].keys.first
31
+ seq_config = current_cluster_config_for(cluster_name || klass)[:seq][sequence_name]
32
+ seq_type = (seq_config[:seq_type] ? seq_config[:seq_type].to_sym : :mysql)
33
+ tables[klass.table_name] ||= (sequences[sequence_name(klass.table_name, klass.primary_key)] ||= sequence_types[seq_type].new(klass, seq_config))
34
+ end
25
35
 
26
- def self.build(klass, sequence_name = nil, cluster_name = nil)
27
- sequence_name ||= current_cluster_config_for(cluster_name || klass)[:seq].keys.first
28
- seq_config = current_cluster_config_for(cluster_name || klass)[:seq][sequence_name]
29
- seq_type = (seq_config[:seq_type] ? seq_config[:seq_type].to_sym : :mysql)
30
- @@tables[klass.table_name] ||= (@@sequences[sequence_name(klass.table_name, klass.primary_key)] ||= @@sequence_types[seq_type].new(klass, seq_config))
31
- end
36
+ def has_sequencer?(table_name)
37
+ !!tables[table_name]
38
+ end
32
39
 
33
- def self.has_sequencer?(table_name)
34
- !!@@tables[table_name]
35
- end
40
+ def sequence_name(table_name, pk)
41
+ "#{table_name}_#{pk || 'id'}_seq"
42
+ end
36
43
 
37
- def self.sequence_name(table_name, pk)
38
- "#{table_name}_#{pk || 'id'}_seq"
39
- end
44
+ def table_name(seq_name)
45
+ seq_name.split("_").first
46
+ end
47
+
48
+ private
40
49
 
41
- def self.table_name(seq_name)
42
- seq_name.split("_").first
50
+ def current_cluster_config_for(klass_or_name)
51
+ cluster_name = if klass_or_name.is_a?(Symbol)
52
+ klass_or_name
53
+ else
54
+ klass_or_name.turntable_cluster_name.to_s
55
+ end
56
+ ActiveRecord::Base.turntable_config[:clusters][cluster_name]
57
+ end
43
58
  end
44
59
 
45
60
  def next_sequence_value
@@ -49,16 +64,5 @@ module ActiveRecord::Turntable
49
64
  def current_sequence_value
50
65
  raise NotImplementedError
51
66
  end
52
-
53
- private
54
-
55
- def self.current_cluster_config_for(klass_or_name)
56
- cluster_name = if klass_or_name.is_a?(Symbol)
57
- klass_or_name
58
- else
59
- klass_or_name.turntable_cluster_name.to_s
60
- end
61
- ActiveRecord::Base.turntable_config[:clusters][cluster_name]
62
- end
63
67
  end
64
68
  end
@@ -33,7 +33,14 @@ module ActiveRecord::Turntable
33
33
  @connection_klass ||= create_connection_class
34
34
  end
35
35
 
36
- def get_or_set_connection_class
36
+ def create_connection_class
37
+ klass = connection_class_instance
38
+ klass.remove_connection
39
+ klass.establish_connection ActiveRecord::Base.connection_pool.spec.config[:shards][name].with_indifferent_access
40
+ klass
41
+ end
42
+
43
+ def connection_class_instance
37
44
  if Connections.const_defined?(name.classify)
38
45
  klass = Connections.const_get(name.classify)
39
46
  else
@@ -43,12 +50,5 @@ module ActiveRecord::Turntable
43
50
  end
44
51
  klass
45
52
  end
46
-
47
- def create_connection_class
48
- klass = get_or_set_connection_class
49
- klass.remove_connection
50
- klass.establish_connection ActiveRecord::Base.connection_pool.spec.config[:shards][name].with_indifferent_access
51
- klass
52
- end
53
53
  end
54
54
  end
@@ -2,22 +2,22 @@ module ActiveRecord::Turntable
2
2
  module ShardingCondition
3
3
  private
4
4
 
5
- def foreign_shard_key
6
- options[:foreign_shard_key] || foreign_target_model.turntable_shard_key
7
- end
5
+ def foreign_shard_key
6
+ options[:foreign_shard_key] || foreign_target_model.turntable_shard_key
7
+ end
8
8
 
9
- def foreign_target_model
10
- respond_to?(:model) ? model : owner
11
- end
9
+ def foreign_target_model
10
+ respond_to?(:model) ? model : owner
11
+ end
12
12
 
13
- def should_use_shard_key?
14
- sharded_by_same_key? || !!options[:foreign_shard_key]
15
- end
13
+ def should_use_shard_key?
14
+ sharded_by_same_key? || !!options[:foreign_shard_key]
15
+ end
16
16
 
17
- def sharded_by_same_key?
18
- foreign_target_model.turntable_enabled? &&
19
- klass.turntable_enabled? &&
20
- foreign_shard_key == klass.turntable_shard_key
21
- end
17
+ def sharded_by_same_key?
18
+ foreign_target_model.turntable_enabled? &&
19
+ klass.turntable_enabled? &&
20
+ foreign_shard_key == klass.turntable_shard_key
21
+ end
22
22
  end
23
23
  end
@@ -1,3 +1,4 @@
1
+ # rubocop:disable Style/CaseEquality
1
2
  require "sql_tree"
2
3
  require "active_support/core_ext/kernel/reporting"
3
4
 
@@ -37,6 +38,7 @@ class SQLTree::Tokenizer
37
38
  end
38
39
 
39
40
  # @note Override to handle x'..' binary string
41
+ # rubocop:disable Lint/EmptyWhen:
40
42
  def each_token(&block) # :yields: SQLTree::Token
41
43
  while next_char
42
44
  case current_char
@@ -47,7 +49,7 @@ class SQLTree::Tokenizer
47
49
  when "," then handle_token(SQLTree::Token::COMMA, &block)
48
50
  when /\d/ then tokenize_number(&block)
49
51
  when "'" then tokenize_quoted_string(&block)
50
- when "E", "x", 'X' then tokenize_possible_escaped_string(&block)
52
+ when "E", "x", "X" then tokenize_possible_escaped_string(&block)
51
53
  when /\w/ then tokenize_keyword(&block)
52
54
  when OPERATOR_CHARS then tokenize_operator(&block)
53
55
  when SQLTree.identifier_quote_char then tokenize_quoted_identifier(&block)
@@ -57,6 +59,7 @@ class SQLTree::Tokenizer
57
59
  # Make sure to yield any tokens that are still stashed on the queue.
58
60
  empty_keyword_queue!(&block)
59
61
  end
62
+ # rubocop:enable Lint/EmptyWhen:
60
63
  alias_method :each, :each_token
61
64
 
62
65
  def tokenize_possible_escaped_string(&block)
@@ -184,7 +187,7 @@ module SQLTree::Node
184
187
  end
185
188
  table_reference
186
189
  else
187
- raise SQLTree::Parser::UnexpectedToken.new(tokens.current)
190
+ raise SQLTree::Parser::UnexpectedToken, tokens.current
188
191
  end
189
192
  end
190
193
  end
@@ -215,7 +218,7 @@ module SQLTree::Node
215
218
  tokens.consume(SQLTree::Token::RPAREN)
216
219
  self.new(hint_method, hint_key, index_list)
217
220
  else
218
- raise SQLTree::Parser::UnexpectedToken.new(tokens.current)
221
+ raise SQLTree::Parser::UnexpectedToken, tokens.current
219
222
  end
220
223
  end
221
224
  end
@@ -350,3 +353,4 @@ module SQLTree::Node
350
353
  end
351
354
  end
352
355
  end
356
+ # rubocop:enable Style/CaseEquality
@@ -1,7 +1,5 @@
1
1
  module ActiveRecord::Turntable
2
2
  module Util
3
- extend self
4
-
5
3
  def ar_version_equals_or_later?(version)
6
4
  ar_version >= Gem::Version.new(version)
7
5
  end
@@ -13,5 +11,9 @@ module ActiveRecord::Turntable
13
11
  def ar_version
14
12
  ActiveRecord.gem_version
15
13
  end
14
+
15
+ module_function :ar_version_equals_or_later?,
16
+ :ar_version_earlier_than?,
17
+ :ar_version
16
18
  end
17
19
  end
@@ -1,5 +1,5 @@
1
1
  module ActiveRecord
2
2
  module Turntable
3
- VERSION = "3.0.0.alpha3".freeze
3
+ VERSION = "3.0.0".freeze
4
4
  end
5
5
  end
@@ -34,7 +34,6 @@ module ActiveRecord::Turntable
34
34
  autoload :SeqShard
35
35
  autoload :Sequencer
36
36
  end
37
- autoload :Helpers
38
37
 
39
38
  included do
40
39
  include ActiveRecordExt
@@ -45,13 +44,15 @@ module ActiveRecord::Turntable
45
44
  DEFAULT_PATH = File.dirname(File.dirname(__FILE__))
46
45
 
47
46
  def turntable_config_file
48
- @@turntable_config_file ||=
49
- File.join(defined?(::Rails) ?
50
- ::Rails.root.to_s : DEFAULT_PATH, "config/turntable.yml")
47
+ @turntable_config_file ||= File.join(turntable_app_root_path, "config/turntable.yml")
51
48
  end
52
49
 
53
50
  def turntable_config_file=(filename)
54
- @@turntable_config_file = filename
51
+ @turntable_config_file = filename
52
+ end
53
+
54
+ def turntable_app_root_path
55
+ defined?(::Rails.root) ? ::Rails.root.to_s : DEFAULT_PATH
55
56
  end
56
57
 
57
58
  def turntable_config
@@ -1,2 +1,3 @@
1
+ # rubocop:disable Style/FileName
1
2
  require "active_record"
2
3
  require "active_record/turntable"