activerecord-turntable 1.1.2 → 2.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (144) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +5 -0
  3. data/.travis.yml +3 -5
  4. data/CHANGELOG.md +70 -0
  5. data/Guardfile +7 -5
  6. data/README.md +490 -0
  7. data/Rakefile +37 -22
  8. data/activerecord-turntable.gemspec +37 -34
  9. data/gemfiles/rails4_0.gemfile +6 -0
  10. data/gemfiles/rails4_1.gemfile +6 -0
  11. data/lib/active_record/turntable/active_record_ext/abstract_adapter.rb +14 -29
  12. data/lib/active_record/turntable/active_record_ext/activerecord_import_ext.rb +45 -0
  13. data/lib/active_record/turntable/active_record_ext/acts_as_archive_extension.rb +21 -0
  14. data/lib/active_record/turntable/active_record_ext/association.rb +85 -0
  15. data/lib/active_record/turntable/active_record_ext/association_preloader.rb +37 -0
  16. data/lib/active_record/turntable/active_record_ext/clever_load.rb +33 -76
  17. data/lib/active_record/turntable/active_record_ext/connection_handler_extension.rb +31 -0
  18. data/lib/active_record/turntable/active_record_ext/database_tasks.rb +81 -0
  19. data/lib/active_record/turntable/active_record_ext/fixtures.rb +54 -42
  20. data/lib/active_record/turntable/active_record_ext/locking_optimistic.rb +101 -0
  21. data/lib/active_record/turntable/active_record_ext/log_subscriber.rb +28 -46
  22. data/lib/active_record/turntable/active_record_ext/migration_proxy.rb +7 -0
  23. data/lib/active_record/turntable/active_record_ext/persistence.rb +96 -94
  24. data/lib/active_record/turntable/active_record_ext/relation.rb +31 -0
  25. data/lib/active_record/turntable/active_record_ext/schema_dumper.rb +18 -28
  26. data/lib/active_record/turntable/active_record_ext/transactions.rb +9 -3
  27. data/lib/active_record/turntable/active_record_ext.rb +26 -11
  28. data/lib/active_record/turntable/algorithm/base.rb +1 -1
  29. data/lib/active_record/turntable/algorithm/range_bsearch_algorithm.rb +1 -1
  30. data/lib/active_record/turntable/algorithm.rb +7 -3
  31. data/lib/active_record/turntable/base.rb +67 -14
  32. data/lib/active_record/turntable/cluster.rb +46 -2
  33. data/lib/active_record/turntable/config.rb +1 -1
  34. data/lib/active_record/turntable/connection_proxy/mixable.rb +7 -29
  35. data/lib/active_record/turntable/connection_proxy.rb +61 -72
  36. data/lib/active_record/turntable/error.rb +5 -6
  37. data/lib/active_record/turntable/helpers.rb +5 -1
  38. data/lib/active_record/turntable/migration.rb +9 -49
  39. data/lib/active_record/turntable/mixer/fader/calculate_shards_sum_result.rb +13 -2
  40. data/lib/active_record/turntable/mixer/fader/select_shards_merge_result.rb +17 -6
  41. data/lib/active_record/turntable/mixer/fader/specified_shard.rb +3 -1
  42. data/lib/active_record/turntable/mixer/fader.rb +12 -10
  43. data/lib/active_record/turntable/mixer.rb +59 -29
  44. data/lib/active_record/turntable/plugin.rb +6 -0
  45. data/lib/active_record/turntable/pool_proxy.rb +12 -19
  46. data/lib/active_record/turntable/rack/query_cache.rb +20 -23
  47. data/lib/active_record/turntable/rack.rb +4 -2
  48. data/lib/active_record/turntable/railtie.rb +4 -3
  49. data/lib/active_record/turntable/railties/databases.rake +81 -122
  50. data/lib/active_record/turntable/seq_shard.rb +1 -1
  51. data/lib/active_record/turntable/sequencer/api.rb +1 -1
  52. data/lib/active_record/turntable/sequencer/barrage.rb +28 -0
  53. data/lib/active_record/turntable/sequencer.rb +27 -9
  54. data/lib/active_record/turntable/shard.rb +2 -2
  55. data/lib/active_record/turntable/sql_tree_patch.rb +1 -1
  56. data/lib/active_record/turntable/version.rb +1 -1
  57. data/lib/active_record/turntable.rb +26 -16
  58. data/lib/generators/templates/turntable.yml +9 -7
  59. data/spec/active_record/turntable/active_record_ext/association_preloader_spec.rb +78 -0
  60. data/spec/active_record/turntable/active_record_ext/association_spec.rb +72 -0
  61. data/spec/active_record/turntable/active_record_ext/clever_load_spec.rb +25 -46
  62. data/spec/active_record/turntable/active_record_ext/locking_optimistic_spec.rb +28 -0
  63. data/spec/active_record/turntable/active_record_ext/persistence_spec.rb +46 -25
  64. data/spec/active_record/turntable/algorithm/range_algorithm_spec.rb +4 -4
  65. data/spec/active_record/turntable/algorithm/range_bsearch_algorithm_spec.rb +35 -0
  66. data/spec/active_record/turntable/algorithm_spec.rb +28 -12
  67. data/spec/active_record/turntable/base_spec.rb +1 -1
  68. data/spec/active_record/turntable/cluster_spec.rb +27 -5
  69. data/spec/active_record/turntable/config_spec.rb +2 -2
  70. data/spec/active_record/turntable/connection_proxy_spec.rb +112 -45
  71. data/spec/active_record/turntable/finder_spec.rb +24 -11
  72. data/spec/active_record/turntable/mixer_spec.rb +21 -21
  73. data/spec/active_record/turntable/rack/query_cache_spec.rb +19 -0
  74. data/spec/active_record/turntable/sequencer/api_spec.rb +38 -0
  75. data/spec/active_record/turntable/sequencer/barrage_spec.rb +22 -0
  76. data/spec/active_record/turntable/sequencer/mysql_spec.rb +22 -0
  77. data/spec/active_record/turntable/shard_spec.rb +1 -1
  78. data/spec/active_record/turntable/transaction_spec.rb +35 -0
  79. data/spec/active_record/turntable_spec.rb +4 -4
  80. data/spec/config/database.yml +24 -34
  81. data/spec/config/turntable.yml +18 -1
  82. data/spec/fabricators/turntable_fabricator.rb +0 -2
  83. data/spec/models/card.rb +3 -0
  84. data/spec/models/cards_user.rb +10 -0
  85. data/spec/models/cards_users_histories.rb +7 -0
  86. data/spec/models/events_users_history.rb +7 -0
  87. data/spec/models/user.rb +7 -0
  88. data/spec/models/user_status.rb +6 -0
  89. data/spec/spec_helper.rb +10 -4
  90. data/spec/support/matchers/be_saved_to.rb +6 -0
  91. data/spec/support/turntable_helper.rb +29 -0
  92. metadata +124 -74
  93. data/README.rdoc +0 -294
  94. data/gemfiles/rails3_0.gemfile +0 -7
  95. data/gemfiles/rails3_1.gemfile +0 -6
  96. data/gemfiles/rails3_2.gemfile +0 -6
  97. data/lib/active_record/turntable/compatible.rb +0 -19
  98. data/sample_app/.gitignore +0 -16
  99. data/sample_app/Gemfile +0 -41
  100. data/sample_app/README.rdoc +0 -261
  101. data/sample_app/Rakefile +0 -7
  102. data/sample_app/app/assets/images/rails.png +0 -0
  103. data/sample_app/app/assets/javascripts/application.js +0 -15
  104. data/sample_app/app/assets/stylesheets/application.css +0 -13
  105. data/sample_app/app/controllers/application_controller.rb +0 -3
  106. data/sample_app/app/helpers/application_helper.rb +0 -2
  107. data/sample_app/app/mailers/.gitkeep +0 -0
  108. data/sample_app/app/models/.gitkeep +0 -0
  109. data/sample_app/app/models/user.rb +0 -4
  110. data/sample_app/app/views/layouts/application.html.erb +0 -14
  111. data/sample_app/config/application.rb +0 -65
  112. data/sample_app/config/boot.rb +0 -6
  113. data/sample_app/config/database.yml +0 -70
  114. data/sample_app/config/environment.rb +0 -5
  115. data/sample_app/config/environments/development.rb +0 -37
  116. data/sample_app/config/environments/production.rb +0 -67
  117. data/sample_app/config/environments/test.rb +0 -37
  118. data/sample_app/config/initializers/backtrace_silencers.rb +0 -7
  119. data/sample_app/config/initializers/inflections.rb +0 -15
  120. data/sample_app/config/initializers/mime_types.rb +0 -5
  121. data/sample_app/config/initializers/secret_token.rb +0 -7
  122. data/sample_app/config/initializers/session_store.rb +0 -8
  123. data/sample_app/config/initializers/wrap_parameters.rb +0 -14
  124. data/sample_app/config/locales/en.yml +0 -5
  125. data/sample_app/config/routes.rb +0 -58
  126. data/sample_app/config/turntable.yml +0 -64
  127. data/sample_app/config.ru +0 -4
  128. data/sample_app/db/migrate/20120316073058_create_users.rb +0 -11
  129. data/sample_app/db/seeds.rb +0 -7
  130. data/sample_app/lib/assets/.gitkeep +0 -0
  131. data/sample_app/lib/tasks/.gitkeep +0 -0
  132. data/sample_app/log/.gitkeep +0 -0
  133. data/sample_app/public/404.html +0 -26
  134. data/sample_app/public/422.html +0 -26
  135. data/sample_app/public/500.html +0 -25
  136. data/sample_app/public/favicon.ico +0 -0
  137. data/sample_app/public/index.html +0 -241
  138. data/sample_app/public/robots.txt +0 -5
  139. data/sample_app/script/rails +0 -6
  140. data/sample_app/vendor/assets/javascripts/.gitkeep +0 -0
  141. data/sample_app/vendor/assets/stylesheets/.gitkeep +0 -0
  142. data/sample_app/vendor/plugins/.gitkeep +0 -0
  143. data/spec/test_models.rb +0 -27
  144. data/spec/turntable_helper.rb +0 -29
@@ -1,41 +1,38 @@
1
+ require 'rack/body_proxy'
1
2
  require 'active_record/query_cache'
2
3
 
3
4
  module ActiveRecord
4
5
  module Turntable
5
6
  module Rack
6
7
  class QueryCache < ActiveRecord::QueryCache
7
- class BodyProxy < ActiveRecord::QueryCache::BodyProxy
8
- def close
9
- @target.close if @target.respond_to?(:close)
10
- ensure
11
- klasses = [ActiveRecord::Base, *ActiveRecord::Base.turntable_connections.values]
12
- ActiveRecord::Base.connection_id = @connection_id
13
- klasses.each do |k|
14
- k.connection.clear_query_cache
15
- unless @original_cache_value
16
- k.connection.disable_query_cache!
17
- end
18
- end
19
- end
20
- end
21
-
22
8
  def call(env)
23
- old = ActiveRecord::Base.connection.query_cache_enabled
24
- klasses = [ActiveRecord::Base, *ActiveRecord::Base.turntable_connections.values]
9
+ enabled = ActiveRecord::Base.connection.query_cache_enabled
10
+ connection_id = ActiveRecord::Base.connection_id
11
+ klasses = ActiveRecord::Base.turntable_connections.values
25
12
  klasses.each do |k|
26
13
  k.connection.enable_query_cache!
27
14
  end
28
15
 
29
- status, headers, body = @app.call(env)
30
- [status, headers, BodyProxy.new(old, body, ActiveRecord::Base.connection_id)]
16
+ response = @app.call(env)
17
+ response[2] = ::Rack::BodyProxy.new(response[2]) do
18
+ restore_query_cache_settings(connection_id, enabled)
19
+ end
20
+
21
+ response
31
22
  rescue Exception => e
23
+ restore_query_cache_settings(connection_id, enabled)
24
+ raise e
25
+ end
26
+
27
+ private
28
+
29
+ def restore_query_cache_settings(connection_id, enabled)
30
+ klasses = ActiveRecord::Base.turntable_connections.values
32
31
  klasses.each do |k|
32
+ ActiveRecord::Base.connection_id = connection_id
33
33
  k.connection.clear_query_cache
34
- unless old
35
- k.connection.disable_query_cache!
36
- end
34
+ k.connection.disable_query_cache! unless enabled
37
35
  end
38
- raise e
39
36
  end
40
37
  end
41
38
  end
@@ -1,6 +1,8 @@
1
1
  module ActiveRecord::Turntable
2
2
  module Rack
3
- autoload :ConnectionManagement, 'active_record/turntable/rack/connection_management'
4
- autoload :QueryCache, 'active_record/turntable/rack/query_cache'
3
+ extend ActiveSupport::Autoload
4
+
5
+ autoload :ConnectionManagement
6
+ autoload :QueryCache
5
7
  end
6
8
  end
@@ -1,6 +1,7 @@
1
1
  module ActiveRecord::Turntable
2
2
  class Railtie < Rails::Railtie
3
3
  rake_tasks do
4
+ require 'active_record/turntable/active_record_ext/database_tasks'
4
5
  load "active_record/turntable/railties/databases.rake"
5
6
  end
6
7
 
@@ -11,9 +12,9 @@ module ActiveRecord::Turntable
11
12
  end
12
13
  end
13
14
 
14
- # Swap QueryCache Middleware
15
- initializer "turntable.swap_query_cache_middleware" do |app|
16
- app.middleware.swap ActiveRecord::QueryCache, ActiveRecord::Turntable::Rack::QueryCache
15
+ # QueryCache Middleware for turntable shards
16
+ initializer "turntable.insert_query_cache_middleware" do |app|
17
+ app.middleware.insert_after ActiveRecord::QueryCache, ActiveRecord::Turntable::Rack::QueryCache
17
18
  end
18
19
  end
19
20
  end
@@ -1,43 +1,69 @@
1
1
  require 'active_record/turntable'
2
2
  ActiveRecord::SchemaDumper.send(:include, ActiveRecord::Turntable::ActiveRecordExt::SchemaDumper)
3
3
 
4
+ # TODO: implement schema:cache:xxxx
5
+
4
6
  db_namespace = namespace :db do
5
- task :create do
6
- if Rails.env.development? && ActiveRecord::Base.configurations['test'] && ActiveRecord::Base.configurations["test"]["shards"]
7
- dbs = ActiveRecord::Base.configurations["test"]["shards"].values
8
- dbs += ActiveRecord::Base.configurations["test"]["seq"].values if ActiveRecord::Base.configurations["test"]["seq"]
9
- dbs.each do |shard_config|
10
- create_database(shard_config)
11
- end
7
+ namespace :create do
8
+ task :all => :load_config do
9
+ ActiveRecord::Tasks::DatabaseTasks.create_all_turntable_cluster
12
10
  end
13
- if shard_configs = ActiveRecord::Base.configurations[Rails.env || 'development']["shards"]
14
- dbs = shard_configs.values
15
- dbs += ActiveRecord::Base.configurations[Rails.env || 'development']["seq"].values if ActiveRecord::Base.configurations[Rails.env || 'development']["seq"]
16
- dbs.each do |shard_config|
17
- create_database(shard_config)
18
- end
11
+ end
12
+
13
+ desc 'Create current turntable databases config/database.yml for the current Rails.env'
14
+ task :create => [:load_config] do
15
+ unless ENV['DATABASE_URL']
16
+ ActiveRecord::Tasks::DatabaseTasks.create_current_turntable_cluster
19
17
  end
20
- config = ActiveRecord::Base.configurations[Rails.env || 'development']
21
- ActiveRecord::Base.establish_connection(config)
22
18
  end
23
19
 
24
- task :drop do
25
- config = ActiveRecord::Base.configurations[Rails.env || 'development']
26
- shard_configs = config["shards"]
27
- if shard_configs
28
- dbs = shard_configs.values
29
- dbs += ActiveRecord::Base.configurations[Rails.env || 'development']["seq"].values if ActiveRecord::Base.configurations[Rails.env || 'development']["seq"]
30
- dbs.each do |shard_config|
31
- begin
32
- drop_database(shard_config)
33
- rescue Exception => e
34
- $stderr.puts "Couldn't drop #{ config['database']} : #{e.inspect}"
35
- end
36
- end
20
+ namespace :drop do
21
+ task :all => :load_config do
22
+ ActiveRecord::Tasks::DatabaseTasks.drop_all_turntable_cluster
23
+ end
24
+ end
25
+
26
+ desc 'Drops current turntable databases for the current Rails.env'
27
+ task :drop => [:load_config] do
28
+ unless ENV['DATABASE_URL']
29
+ ActiveRecord::Tasks::DatabaseTasks.drop_current_turntable_cluster
30
+ end
31
+ end
32
+
33
+ desc "Migrate turntable databases (options: VERSION=x, VERBOSE=false, SCOPE=blog)."
34
+ task :migrate => [:environment, :load_config] do
35
+ ActiveRecord::Migration.verbose = ENV["VERBOSE"] ? ENV["VERBOSE"] == "true" : true
36
+
37
+ ActiveRecord::Tasks::DatabaseTasks.each_current_turntable_cluster_connected do |name, configuration|
38
+ puts "[turntable] *** Migrating database: #{configuration['database']}(Shard: #{name})"
39
+ ActiveRecord::Migrator.migrate(ActiveRecord::Migrator.migrations_paths, ENV["VERSION"] ? ENV["VERSION"].to_i : nil)
40
+ db_namespace['_dump'].invoke
37
41
  end
38
- ActiveRecord::Base.establish_connection(config)
39
42
  end
40
43
 
44
+ desc 'Rolls the turntable cluster schema back to the previous version (specify steps w/ STEP=n).'
45
+ task :rollback => [:environment, :load_config] do
46
+ step = ENV['STEP'] ? ENV['STEP'].to_i : 1
47
+
48
+ ActiveRecord::Tasks::DatabaseTasks.each_current_turntable_cluster_connected do |name, configuration|
49
+ puts "[turntable] *** Migrating database: #{configuration['database']}(Shard: #{name})"
50
+ ActiveRecord::Migrator.rollback(ActiveRecord::Migrator.migrations_paths, step)
51
+ end
52
+ db_namespace['_dump'].invoke
53
+ end
54
+
55
+ # desc 'Pushes the turntable cluster schema to the next version (specify steps w/ STEP=n).'
56
+ task :forward => [:environment, :load_config] do
57
+ step = ENV['STEP'] ? ENV['STEP'].to_i : 1
58
+
59
+ ActiveRecord::Tasks::DatabaseTasks.each_current_turntable_cluster_connected do |name, configuration|
60
+ puts "[turntable] *** Migrating database: #{configuration['database']}(Shard: #{name})"
61
+ ActiveRecord::Migrator.forward(ActiveRecord::Migrator.migrations_paths, step)
62
+ end
63
+ db_namespace['_dump'].invoke
64
+ end
65
+
66
+
41
67
  namespace :schema do
42
68
  task :dump do
43
69
  require 'active_record/schema_dumper'
@@ -46,6 +72,7 @@ db_namespace = namespace :db do
46
72
  shard_configs.merge!(config["seq"]) if config["seq"]
47
73
  if shard_configs
48
74
  shard_configs.each do |name, config|
75
+ next unless config["database"]
49
76
  filename = ENV['SCHEMA'] || "#{Rails.root}/db/schema-#{name}.rb"
50
77
  File.open(filename, "w:utf-8") do |file|
51
78
  ActiveRecord::Base.establish_connection(config)
@@ -64,6 +91,7 @@ db_namespace = namespace :db do
64
91
  shard_configs.merge!(config["seq"]) if config["seq"]
65
92
  if shard_configs
66
93
  shard_configs.each do |name, config|
94
+ next unless config["database"]
67
95
  ActiveRecord::Base.establish_connection(config)
68
96
  file = ENV['SCHEMA'] || "#{Rails.root}/db/schema-#{name}.rb"
69
97
  if File.exists?(file)
@@ -80,90 +108,45 @@ db_namespace = namespace :db do
80
108
  namespace :structure do
81
109
  desc 'Dump the database structure to an SQL file'
82
110
  task :dump => :environment do
83
- config = ActiveRecord::Base.configurations[Rails.env]
84
- shard_configs = config["shards"]
111
+ current_config = ActiveRecord::Tasks::DatabaseTasks.current_config
112
+ shard_configs = current_config["shards"]
85
113
  shard_configs.merge!(config["seq"]) if config["seq"]
86
114
  if shard_configs
87
115
  shard_configs.each do |name, config|
88
- case config['adapter']
89
- when /mysql/, 'oci', 'oracle'
90
- ActiveRecord::Base.establish_connection(config)
91
- File.open("#{Rails.root}/db/#{Rails.env}_#{name}_structure.sql", "w+") { |f| f << ActiveRecord::Base.connection.structure_dump }
92
- when /postgresql/
93
- ENV['PGHOST'] = config['host'] if config['host']
94
- ENV['PGPORT'] = config["port"].to_s if config['port']
95
- ENV['PGPASSWORD'] = config['password'].to_s if config['password']
96
- search_path = config['schema_search_path']
97
- unless search_path.blank?
98
- search_path = search_path.split(",").map{|search_path| "--schema=#{search_path.strip}" }.join(" ")
99
- end
100
- `pg_dump -i -U "#{config['username']}" -s -x -O -f db/#{Rails.env}_#{name}_structure.sql #{search_path} #{config['database']}`
101
- raise 'Error dumping database' if $?.exitstatus == 1
102
- when /sqlite/
103
- dbfile = config['database'] || config['dbfile']
104
- `sqlite3 #{dbfile} .schema > db/#{Rails.env}_#{name}_structure.sql`
105
- when 'sqlserver'
106
- `smoscript -s #{config['host']} -d #{config['database']} -u #{config['username']} -p #{config['password']} -f db\\#{Rails.env}_#{name}_structure.sql -A -U`
107
- when "firebird"
108
- set_firebird_env(config)
109
- db_string = firebird_db_string(config)
110
- sh "isql -a #{db_string} > #{Rails.root}/db/#{Rails.env}_#{name}_structure.sql"
111
- else
112
- raise "Task not supported by '#{config["adapter"]}'"
113
- end
116
+ next unless config["database"]
117
+ ActiveRecord::Base.establish_connection(config)
118
+ filename = File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, "structure_#{name}.sql")
119
+ ActiveRecord::Tasks::DatabaseTasks.structure_dump(config, filename)
114
120
 
115
121
  if ActiveRecord::Base.connection.supports_migrations?
116
- File.open("#{Rails.root}/db/#{Rails.env}_#{name}_structure.sql", "a") { |f| f << ActiveRecord::Base.connection.dump_schema_information }
122
+ File.open(filename, "a") do |f|
123
+ f.puts ActiveRecord::Base.connection.dump_schema_information
124
+ end
117
125
  end
118
126
  end
127
+ ActiveRecord::Base.establish_connection(current_config)
119
128
  end
120
- ActiveRecord::Base.establish_connection(config)
129
+ db_namespace['structure:dump'].reenable
121
130
  end
122
- end
123
-
124
131
 
125
- namespace :test do
126
- # desc "Recreate the test databases from the development structure"
127
- task :clone_structure do
128
- config = ActiveRecord::Base.configurations[Rails.env]
129
- shard_configs = config["shards"]
132
+ # desc "Recreate the databases from the structure.sql file"
133
+ task :load => [:environment, :load_config] do
134
+ current_config = ActiveRecord::Tasks::DatabaseTasks.current_config
135
+ shard_configs = current_config["shards"]
130
136
  shard_configs.merge!(config["seq"]) if config["seq"]
131
137
  if shard_configs
132
138
  shard_configs.each do |name, config|
133
- case config['adapter']
134
- when /mysql/
135
- ActiveRecord::Base.establish_connection(config)
136
- ActiveRecord::Base.connection.execute('SET foreign_key_checks = 0')
137
- IO.readlines("#{Rails.root}/db/#{Rails.env}_#{name}_structure.sql").join.split("\n\n").each do |table|
138
- ActiveRecord::Base.connection.execute(table)
139
- end
140
- when /postgresql/
141
- ENV['PGHOST'] = config['host'] if config['host']
142
- ENV['PGPORT'] = config['port'].to_s if config['port']
143
- ENV['PGPASSWORD'] = config['password'].to_s if config['password']
144
- `psql -U "#{config['username']}" -f "#{Rails.root}/db/#{Rails.env}#{name}_structure.sql" #{config['database']} #{config['template']}`
145
- when /sqlite/
146
- dbfile = config['database'] || config['dbfile']
147
- `sqlite3 #{dbfile} < "#{Rails.root}/db/#{Rails.env}#{name}_structure.sql"`
148
- when 'sqlserver'
149
- `sqlcmd -S #{config['host']} -d #{config['database']} -U #{config['username']} -P #{config['password']} -i db\\#{Rails.env}#{name}_structure.sql`
150
- when 'oci', 'oracle'
151
- ActiveRecord::Base.establish_connection(config)
152
- IO.readlines("#{Rails.root}/db/#{Rails.env}#{name}_structure.sql").join.split(";\n\n").each do |ddl|
153
- ActiveRecord::Base.connection.execute(ddl)
154
- end
155
- when 'firebird'
156
- set_firebird_env(config)
157
- db_string = firebird_db_string(config)
158
- sh "isql -i #{Rails.root}/db/#{Rails.env}#{name}_structure.sql #{db_string}"
159
- else
160
- raise "Task not supported by '#{config['adapter']}'"
161
- end
139
+ next unless config["database"]
140
+ ActiveRecord::Base.establish_connection(config)
141
+ filename = File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, "structure_#{name}.sql")
142
+ ActiveRecord::Tasks::DatabaseTasks.structure_load(config, filename)
162
143
  end
144
+ ActiveRecord::Base.establish_connection(current_config)
163
145
  end
164
- ActiveRecord::Base.establish_connection(config)
165
146
  end
147
+ end
166
148
 
149
+ namespace :test do
167
150
  # desc "Empty the test database"
168
151
  task :purge => :environment do
169
152
  config = ActiveRecord::Base.configurations[Rails.env]
@@ -171,35 +154,11 @@ db_namespace = namespace :db do
171
154
  shard_configs.merge!(config["seq"]) if config["seq"]
172
155
  if shard_configs
173
156
  shard_configs.each do |name, config|
174
- case config['adapter']
175
- when /mysql/
176
- ActiveRecord::Base.establish_connection(config)
177
- ActiveRecord::Base.connection.recreate_database(config['database'], mysql_creation_options(config))
178
- when /postgresql/
179
- ActiveRecord::Base.clear_active_connections!
180
- drop_database(config)
181
- create_database(config)
182
- when /sqlite/
183
- dbfile = config['database'] || config['dbfile']
184
- File.delete(dbfile) if File.exist?(dbfile)
185
- when 'sqlserver'
186
- # TODO
187
- when "oci", "oracle"
188
- ActiveRecord::Base.establish_connection(config)
189
- ActiveRecord::Base.connection.structure_drop.split(";\n\n").each do |ddl|
190
- ActiveRecord::Base.connection.execute(ddl)
191
- end
192
- when 'firebird'
193
- ActiveRecord::Base.establish_connection(config)
194
- ActiveRecord::Base.connection.recreate_database!
195
- else
196
- raise "Task not supported by '#{config['adapter']}'"
197
- end
157
+ next unless config["database"]
158
+ ActiveRecord::Tasks::DatabaseTasks.purge config
198
159
  end
199
160
  end
200
161
  ActiveRecord::Base.establish_connection(config)
201
162
  end
202
163
  end
203
-
204
164
  end
205
-
@@ -1,6 +1,7 @@
1
1
  module ActiveRecord::Turntable
2
2
  class SeqShard < Shard
3
3
  private
4
+
4
5
  def retrieve_connection_pool
5
6
  ActiveRecord::Base.turntable_connections[name] ||=
6
7
  begin
@@ -11,4 +12,3 @@ module ActiveRecord::Turntable
11
12
  end
12
13
  end
13
14
  end
14
-
@@ -1,6 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  #
3
- # APIサーバを利用しての採番
3
+ # Sequencer via HTTP API
4
4
  #
5
5
  require 'httpclient'
6
6
 
@@ -0,0 +1,28 @@
1
+ module ActiveRecord::Turntable
2
+ class Sequencer
3
+ class Barrage < Sequencer
4
+ @@unique_barrage_instance = {}
5
+
6
+ def initialize(klass, options = {})
7
+ require 'barrage'
8
+ @klass = klass
9
+ @options = options["options"]
10
+ @barrage = get_barrage_instance
11
+ end
12
+
13
+ def next_sequence_value(sequence_name)
14
+ @barrage.next
15
+ end
16
+
17
+ def current_sequence_value(sequence_name)
18
+ @barrage.current
19
+ end
20
+
21
+ private
22
+
23
+ def get_barrage_instance
24
+ @@unique_barrage_instance[@options] ||= ::Barrage.new(@options)
25
+ end
26
+ end
27
+ end
28
+ end
@@ -5,20 +5,27 @@
5
5
 
6
6
  module ActiveRecord::Turntable
7
7
  class Sequencer
8
- autoload :Api, "active_record/turntable/sequencer/api"
9
- autoload :Mysql, "active_record/turntable/sequencer/mysql"
8
+ extend ActiveSupport::Autoload
9
+
10
+ eager_autoload do
11
+ autoload :Api
12
+ autoload :Mysql
13
+ autoload :Barrage
14
+ end
15
+
10
16
  @@sequence_types = {
11
17
  :api => Api,
12
- :mysql => Mysql
18
+ :mysql => Mysql,
19
+ :barrage => Barrage
13
20
  }
14
21
 
15
22
  @@sequences = {}
16
23
  @@tables = {}
17
24
  cattr_reader :sequences, :tables
18
25
 
19
- def self.build(klass)
20
- seq_config_name = ActiveRecord::Base.turntable_config["clusters"][klass.turntable_cluster_name.to_s]["seq"]["connection"]
21
- seq_config = ActiveRecord::Base.configurations[Rails.env]["seq"][seq_config_name]
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]
22
29
  seq_type = (seq_config["seq_type"] ? seq_config["seq_type"].to_sym : :mysql)
23
30
  @@tables[klass.table_name] ||= (@@sequences[sequence_name(klass.table_name, klass.primary_key)] ||= @@sequence_types[seq_type].new(klass, seq_config))
24
31
  end
@@ -28,7 +35,7 @@ module ActiveRecord::Turntable
28
35
  end
29
36
 
30
37
  def self.sequence_name(table_name, pk)
31
- "#{ table_name}_#{pk || 'id'}_seq"
38
+ "#{table_name}_#{pk || 'id'}_seq"
32
39
  end
33
40
 
34
41
  def self.table_name(seq_name)
@@ -36,11 +43,22 @@ module ActiveRecord::Turntable
36
43
  end
37
44
 
38
45
  def next_sequence_value
39
- raise ActiveRecord::Turntable::NotImplementedError
46
+ raise NotImplementedError
40
47
  end
41
48
 
42
49
  def current_sequence_value
43
- raise ActiveRecord::Turntable::NotImplementedError
50
+ raise NotImplementedError
51
+ 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]
44
62
  end
45
63
  end
46
64
  end
@@ -41,8 +41,8 @@ module ActiveRecord::Turntable
41
41
  raise "Please install the #{config['adapter']} adapter: `gem install activerecord-#{config['adapter']}-adapter` (#{e})"
42
42
  end
43
43
  adapter_method = "#{config['adapter']}_connection"
44
- ActiveRecord::Base::ConnectionSpecification.new(config, adapter_method)
44
+
45
+ ActiveRecord::ConnectionAdapters::ConnectionSpecification.new(config, adapter_method)
45
46
  end
46
47
  end
47
48
  end
48
-
@@ -46,7 +46,7 @@ module SQLTree::Node
46
46
  sql << " GROUP BY " << group_by.map { |g| g.to_sql(options) }.join(', ') if group_by
47
47
  sql << " ORDER BY " << order_by.map { |o| o.to_sql(options) }.join(', ') if order_by
48
48
  sql << " HAVING " << having.to_sql(options) if having
49
- sql << " LIMIT " << limit.map {|f| f.to_sql(options) }.join(', ') if limit
49
+ sql << " LIMIT " << Array(limit).map {|f| f.to_sql(options) }.join(', ') if limit
50
50
  sql << " OFFSET " << offset.to_sql(options) if offset
51
51
  return sql
52
52
  end
@@ -1,5 +1,5 @@
1
1
  module ActiveRecord
2
2
  module Turntable
3
- VERSION = "1.1.2"
3
+ VERSION = "2.0.0.rc1"
4
4
  end
5
5
  end
@@ -13,23 +13,25 @@ require 'singleton'
13
13
 
14
14
  module ActiveRecord::Turntable
15
15
  extend ActiveSupport::Concern
16
+ extend ActiveSupport::Autoload
16
17
 
17
- autoload :ActiveRecordExt, 'active_record/turntable/active_record_ext'
18
- autoload :Algorithm, 'active_record/turntable/algorithm'
19
- autoload :Base, 'active_record/turntable/base'
20
- autoload :Cluster, 'active_record/turntable/cluster'
21
- autoload :Config, 'active_record/turntable/config'
22
- autoload :Compatible, "active_record/turntable/compatible"
23
- autoload :ConnectionProxy, 'active_record/turntable/connection_proxy'
24
- autoload :Helpers, 'active_record/turntable/helpers'
25
- autoload :MasterShard, 'active_record/turntable/master_shard'
26
- autoload :Migration, 'active_record/turntable/migration'
27
- autoload :Mixer, 'active_record/turntable/mixer'
28
- autoload :PoolProxy, 'active_record/turntable/pool_proxy'
29
- autoload :Rack, 'active_record/turntable/rack'
30
- autoload :SeqShard, 'active_record/turntable/seq_shard'
31
- autoload :Sequencer, 'active_record/turntable/sequencer'
32
- autoload :Shard, 'active_record/turntable/shard'
18
+ eager_autoload do
19
+ autoload :ActiveRecordExt
20
+ autoload :Algorithm
21
+ autoload :Base
22
+ autoload :Cluster
23
+ autoload :Config
24
+ autoload :ConnectionProxy
25
+ autoload :MasterShard
26
+ autoload :Migration
27
+ autoload :Mixer
28
+ autoload :PoolProxy
29
+ autoload :Shard
30
+ autoload :SeqShard
31
+ autoload :Sequencer
32
+ end
33
+ autoload :Rack
34
+ autoload :Helpers
33
35
 
34
36
  included do
35
37
  include ActiveRecordExt
@@ -54,5 +56,13 @@ module ActiveRecord::Turntable
54
56
  end
55
57
  end
56
58
 
59
+ def self.rails4?
60
+ ActiveRecord::VERSION::MAJOR == 4
61
+ end
62
+
63
+ def self.rails41_later?
64
+ rails4? && ActiveRecord::VERSION::MINOR >= 1
65
+ end
66
+
57
67
  require "active_record/turntable/railtie" if defined?(Rails)
58
68
  end
@@ -5,9 +5,10 @@
5
5
  development:
6
6
  clusters:
7
7
  user_cluster:
8
- algorithm: range
8
+ algorithm: range_bsearch
9
9
  seq:
10
- connection: user_seq_1
10
+ user_seq:
11
+ connection: user_seq
11
12
  shards:
12
13
  - connection: user_shard_1
13
14
  less_than: 100
@@ -19,9 +20,10 @@ development:
19
20
  test:
20
21
  clusters:
21
22
  user_cluster:
22
- algorithm: range
23
+ algorithm: range_bsearch
23
24
  seq:
24
- connection: user_seq_1
25
+ user_seq:
26
+ connection: user_seq
25
27
  shards:
26
28
  - connection: user_shard_1
27
29
  less_than: 20000
@@ -33,9 +35,10 @@ test:
33
35
  production:
34
36
  clusters:
35
37
  user_cluster:
36
- algorithm: range
38
+ algorithm: range_bsearch
37
39
  seq:
38
- connection: user_seq_1
40
+ user_seq:
41
+ connection: user_seq
39
42
  shards:
40
43
  - connection: user_shard_1
41
44
  less_than: 20000
@@ -43,4 +46,3 @@ production:
43
46
  less_than: 40000
44
47
  - connection: user_shard_3
45
48
  less_than: 10000000
46
-