active_record_shards 3.17.0 → 4.0.0.beta1

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.
@@ -1,8 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- ActiveRecord::ConnectionAdapters::ConnectionHandler.class_eval do
4
- remove_method :retrieve_connection_pool
5
- def retrieve_connection_pool(klass)
6
- class_to_pool[klass.connection_pool_name] ||= pool_for(klass)
7
- end
8
- end
@@ -1,36 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ActiveRecordShards
4
- ConnectionPoolNameDecorator = Struct.new(:name)
5
-
6
- # It overrides given connection handler methods (they differ depend on
7
- # Rails version).
8
- #
9
- # It takes the first argument, ActiveRecord::Base object or
10
- # String (connection_pool_name), converts it in Struct object and
11
- # passes to the original method.
12
- #
13
- # Example:
14
- # methods_to_override = [:establish_connection, :remove_connection]
15
- # ActiveRecordShards.override_connection_handler_methods(methods_to_override)
16
- #
17
- def self.override_connection_handler_methods(method_names)
18
- method_names.each do |method_name|
19
- ActiveRecord::ConnectionAdapters::ConnectionHandler.class_eval do
20
- define_method("#{method_name}_with_connection_pool_name") do |*args|
21
- unless args[0].is_a? ConnectionPoolNameDecorator
22
- name = if args[0].is_a? String
23
- args[0]
24
- else
25
- args[0].connection_pool_name
26
- end
27
- args[0] = ConnectionPoolNameDecorator.new(name)
28
- end
29
- send("#{method_name}_without_connection_pool_name", *args)
30
- end
31
- alias_method :"#{method_name}_without_connection_pool_name", method_name
32
- alias_method method_name, :"#{method_name}_with_connection_pool_name"
33
- end
34
- end
35
- end
36
- end
@@ -1,19 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class << ActiveRecord::Base
4
- remove_method :establish_connection if ActiveRecord::VERSION::MAJOR >= 5
5
- def establish_connection(spec = ENV["DATABASE_URL"])
6
- spec ||= ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
7
- spec = spec.to_sym if spec.is_a?(String)
8
- resolver = ActiveRecordShards::ConnectionSpecification::Resolver.new configurations
9
- spec = resolver.spec(spec)
10
-
11
- unless respond_to?(spec.adapter_method)
12
- raise AdapterNotFound, "database configuration specifies nonexistent #{spec.config[:adapter]} adapter"
13
- end
14
-
15
- remove_connection
16
- specification_cache[connection_pool_name] = spec
17
- connection_handler.establish_connection self, spec
18
- end
19
- end
@@ -1,56 +0,0 @@
1
- module ActiveRecordShards
2
- module ConnectionSwitcher
3
- # Name of the connection pool. Used by ConnectionHandler to retrieve the current connection pool.
4
- def connection_pool_name # :nodoc:
5
- name = current_shard_selection.shard_name(self)
6
-
7
- # e.g. if "production_slave" is not defined in `Configuration`, fall back to "production"
8
- if configurations[name].nil? && on_slave?
9
- current_shard_selection.shard_name(self, false)
10
- else
11
- name
12
- end
13
- end
14
-
15
- private
16
-
17
- def ensure_shard_connection
18
- establish_shard_connection unless connected_to_shard?
19
- end
20
-
21
- def establish_shard_connection
22
- name = connection_pool_name
23
- spec = configurations[name]
24
-
25
- if spec.nil?
26
- raise ActiveRecord::AdapterNotSpecified, "No database defined by #{name} in your database config. (configurations: #{configurations.keys.inspect})"
27
- end
28
-
29
- specification_cache[name] ||= begin
30
- resolver = ActiveRecordShards::ConnectionSpecification::Resolver.new configurations
31
- resolver.spec(spec)
32
- end
33
-
34
- connection_handler.establish_connection(self, specification_cache[name])
35
- end
36
-
37
- def specification_cache
38
- @@specification_cache ||= {}
39
- end
40
-
41
- # Helper method to clear global state when testing.
42
- def clear_specification_cache
43
- @@specification_cache = {}
44
- end
45
-
46
- def connection_pool_key
47
- specification_cache[connection_pool_name]
48
- end
49
-
50
- def connected_to_shard?
51
- specs_to_pools = Hash[connection_handler.connection_pool_list.map { |pool| [pool.spec, pool] }]
52
-
53
- specs_to_pools.key?(connection_pool_key)
54
- end
55
- end
56
- end
@@ -1,125 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ActiveRecord
4
- class Migrator
5
- def self.shards_migration_context
6
- if ActiveRecord::VERSION::MAJOR >= 6
7
- ActiveRecord::MigrationContext.new(ActiveRecord::Migrator.migrations_paths, ActiveRecord::SchemaMigration)
8
- elsif ActiveRecord::VERSION::STRING >= '5.2.0'
9
- ActiveRecord::MigrationContext.new(ActiveRecord::Migrator.migrations_paths)
10
- else
11
- self
12
- end
13
- end
14
-
15
- def initialize_with_sharding(*args)
16
- initialize_without_sharding(*args)
17
-
18
- # Rails creates the internal tables on the unsharded DB. We make them
19
- # manually on the sharded DBs.
20
- ActiveRecord::Base.on_all_shards do
21
- ActiveRecord::SchemaMigration.create_table
22
- if ActiveRecord::VERSION::MAJOR >= 5
23
- ActiveRecord::InternalMetadata.create_table
24
- end
25
- end
26
- end
27
- alias_method :initialize_without_sharding, :initialize
28
- alias_method :initialize, :initialize_with_sharding
29
-
30
- def run_with_sharding
31
- ActiveRecord::Base.on_shard(nil) { run_without_sharding }
32
- ActiveRecord::Base.on_all_shards { run_without_sharding }
33
- end
34
- alias_method :run_without_sharding, :run
35
- alias_method :run, :run_with_sharding
36
-
37
- def migrate_with_sharding
38
- ActiveRecord::Base.on_shard(nil) { migrate_without_sharding }
39
- ActiveRecord::Base.on_all_shards { migrate_without_sharding }
40
- end
41
- alias_method :migrate_without_sharding, :migrate
42
- alias_method :migrate, :migrate_with_sharding
43
-
44
- # don't allow Migrator class to cache versions
45
- undef migrated
46
- def migrated
47
- self.class.shards_migration_context.get_all_versions
48
- end
49
-
50
- # list of pending migrations is any migrations that haven't run on all shards.
51
- undef pending_migrations
52
- def pending_migrations
53
- pending, _missing = self.class.shard_status(migrations.map(&:version))
54
- pending = pending.values.flatten
55
- migrations.select { |m| pending.include?(m.version) }
56
- end
57
-
58
- # public
59
- # list of pending and missing versions per shard
60
- # [{1 => [1234567]}, {1 => [2345678]}]
61
- def self.shard_status(versions)
62
- pending = {}
63
- missing = {}
64
-
65
- collect = lambda do |shard|
66
- migrated = shards_migration_context.get_all_versions
67
-
68
- p = versions - migrated
69
- pending[shard] = p if p.any?
70
-
71
- m = migrated - versions
72
- missing[shard] = m if m.any?
73
- end
74
-
75
- ActiveRecord::Base.on_shard(nil) { collect.call(nil) }
76
- ActiveRecord::Base.on_all_shards { |shard| collect.call(shard) }
77
-
78
- [pending, missing]
79
- end
80
- end
81
- end
82
-
83
- module ActiveRecordShards
84
- module MigrationClassExtension
85
- attr_accessor :migration_shard
86
-
87
- def shard(arg = nil)
88
- self.migration_shard = arg
89
- end
90
- end
91
-
92
- module ActualMigrationExtension
93
- def migrate_with_forced_shard(direction)
94
- if migration_shard.blank?
95
- raise "#{name}: Can't run migrations without a shard spec: this may be :all, :none,
96
- or a specific shard (for data-fixups). please call shard(arg) in your migration."
97
- end
98
-
99
- shard = ActiveRecord::Base.current_shard_selection.shard
100
-
101
- if shard.nil?
102
- return if migration_shard != :none
103
- else
104
- return if migration_shard == :none
105
- return if migration_shard != :all && migration_shard.to_s != shard.to_s
106
- end
107
-
108
- migrate_without_forced_shard(direction)
109
- end
110
-
111
- def migration_shard
112
- self.class.migration_shard
113
- end
114
- end
115
- end
116
-
117
- ActiveRecord::Migration.class_eval do
118
- extend ActiveRecordShards::MigrationClassExtension
119
- include ActiveRecordShards::ActualMigrationExtension
120
-
121
- alias_method :migrate_without_forced_shard, :migrate
122
- alias_method :migrate, :migrate_with_forced_shard
123
- end
124
-
125
- ActiveRecord::MigrationProxy.delegate :migration_shard, to: :migration
@@ -1,9 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'active_record_shards/connection_pool'
4
- require 'active_record_shards/connection_handler'
5
- require 'active_record_shards/connection_specification'
6
-
7
- ActiveRecordShards::ConnectionSpecification = ActiveRecord::ConnectionAdapters::ConnectionSpecification
8
- methods_to_override = [:establish_connection, :remove_connection, :pool_for, :pool_from_any_process_for]
9
- ActiveRecordShards.override_connection_handler_methods(methods_to_override)
@@ -1,42 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ActiveRecordShards
4
- module SchemaDumperExtension
5
- def dump(stream)
6
- stream = super(stream)
7
- original_connection = @connection
8
-
9
- if ActiveRecord::Base.supports_sharding?
10
- ActiveRecord::Base.on_first_shard do
11
- @connection = ActiveRecord::Base.connection
12
- shard_header(stream)
13
- extensions(stream)
14
- tables(stream)
15
- shard_trailer(stream)
16
- end
17
- end
18
-
19
- stream
20
- ensure
21
- @connection = original_connection
22
- end
23
-
24
- def shard_header(stream)
25
- define_params = @version ? "version: #{@version}" : ""
26
-
27
- stream.puts <<~HEADER
28
-
29
-
30
- # This section generated by active_record_shards
31
-
32
- ActiveRecord::Base.on_all_shards do
33
- ActiveRecord::Schema.define(#{define_params}) do
34
-
35
- HEADER
36
- end
37
-
38
- def shard_trailer(stream)
39
- stream.puts "end\nend"
40
- end
41
- end
42
- end