activerecord 7.2.2.1 → 8.1.2
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +564 -753
- data/README.rdoc +2 -2
- data/lib/active_record/association_relation.rb +2 -1
- data/lib/active_record/associations/alias_tracker.rb +6 -4
- data/lib/active_record/associations/association.rb +35 -11
- data/lib/active_record/associations/belongs_to_association.rb +18 -2
- data/lib/active_record/associations/builder/association.rb +23 -11
- data/lib/active_record/associations/builder/belongs_to.rb +17 -4
- data/lib/active_record/associations/builder/collection_association.rb +7 -3
- data/lib/active_record/associations/builder/has_one.rb +1 -1
- data/lib/active_record/associations/builder/singular_association.rb +33 -5
- data/lib/active_record/associations/collection_association.rb +10 -8
- data/lib/active_record/associations/collection_proxy.rb +22 -4
- data/lib/active_record/associations/deprecation.rb +88 -0
- data/lib/active_record/associations/disable_joins_association_scope.rb +1 -1
- data/lib/active_record/associations/errors.rb +3 -0
- data/lib/active_record/associations/has_many_through_association.rb +3 -2
- data/lib/active_record/associations/join_dependency/join_association.rb +25 -27
- data/lib/active_record/associations/join_dependency.rb +4 -2
- data/lib/active_record/associations/preloader/association.rb +2 -2
- data/lib/active_record/associations/preloader/batch.rb +7 -1
- data/lib/active_record/associations/preloader/branch.rb +1 -0
- data/lib/active_record/associations/singular_association.rb +8 -3
- data/lib/active_record/associations.rb +192 -24
- data/lib/active_record/asynchronous_queries_tracker.rb +28 -24
- data/lib/active_record/attribute_methods/primary_key.rb +4 -8
- data/lib/active_record/attribute_methods/query.rb +34 -0
- data/lib/active_record/attribute_methods/serialization.rb +17 -4
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -14
- data/lib/active_record/attribute_methods.rb +24 -19
- data/lib/active_record/attributes.rb +40 -26
- data/lib/active_record/autosave_association.rb +91 -39
- data/lib/active_record/base.rb +3 -4
- data/lib/active_record/coders/json.rb +14 -5
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +35 -28
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +16 -4
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +51 -13
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +458 -117
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +136 -74
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +44 -11
- data/lib/active_record/connection_adapters/abstract/quoting.rb +16 -25
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +11 -7
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +37 -36
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +2 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +122 -29
- data/lib/active_record/connection_adapters/abstract/transaction.rb +40 -8
- data/lib/active_record/connection_adapters/abstract_adapter.rb +175 -87
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +77 -58
- data/lib/active_record/connection_adapters/column.rb +17 -4
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +4 -4
- data/lib/active_record/connection_adapters/mysql/quoting.rb +7 -9
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +2 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +41 -10
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +73 -46
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +89 -94
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +10 -11
- data/lib/active_record/connection_adapters/pool_config.rb +7 -7
- data/lib/active_record/connection_adapters/postgresql/column.rb +4 -0
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +76 -45
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +10 -0
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +21 -10
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -4
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +9 -17
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +28 -45
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +69 -32
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +140 -64
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +83 -105
- data/lib/active_record/connection_adapters/schema_cache.rb +3 -5
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +90 -98
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +13 -8
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +0 -6
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +27 -2
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +13 -13
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +112 -42
- data/lib/active_record/connection_adapters/statement_pool.rb +4 -2
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +38 -67
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +2 -19
- data/lib/active_record/connection_adapters.rb +1 -56
- data/lib/active_record/connection_handling.rb +37 -10
- data/lib/active_record/core.rb +61 -25
- data/lib/active_record/counter_cache.rb +34 -9
- data/lib/active_record/database_configurations/connection_url_resolver.rb +3 -1
- data/lib/active_record/database_configurations/database_config.rb +9 -1
- data/lib/active_record/database_configurations/hash_config.rb +67 -9
- data/lib/active_record/database_configurations/url_config.rb +13 -3
- data/lib/active_record/database_configurations.rb +7 -3
- data/lib/active_record/delegated_type.rb +19 -19
- data/lib/active_record/dynamic_matchers.rb +54 -69
- data/lib/active_record/encryption/config.rb +3 -1
- data/lib/active_record/encryption/encryptable_record.rb +9 -9
- data/lib/active_record/encryption/encrypted_attribute_type.rb +12 -3
- data/lib/active_record/encryption/encryptor.rb +49 -28
- data/lib/active_record/encryption/extended_deterministic_queries.rb +4 -2
- data/lib/active_record/encryption/scheme.rb +9 -2
- data/lib/active_record/enum.rb +46 -42
- data/lib/active_record/errors.rb +36 -12
- data/lib/active_record/explain.rb +1 -1
- data/lib/active_record/explain_registry.rb +51 -2
- data/lib/active_record/filter_attribute_handler.rb +73 -0
- data/lib/active_record/fixture_set/table_row.rb +19 -2
- data/lib/active_record/fixtures.rb +2 -4
- data/lib/active_record/future_result.rb +13 -9
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +1 -1
- data/lib/active_record/insert_all.rb +12 -7
- data/lib/active_record/locking/optimistic.rb +8 -1
- data/lib/active_record/locking/pessimistic.rb +5 -0
- data/lib/active_record/log_subscriber.rb +3 -13
- data/lib/active_record/middleware/shard_selector.rb +34 -17
- data/lib/active_record/migration/command_recorder.rb +44 -11
- data/lib/active_record/migration/compatibility.rb +37 -24
- data/lib/active_record/migration/default_schema_versions_formatter.rb +30 -0
- data/lib/active_record/migration.rb +50 -43
- data/lib/active_record/model_schema.rb +38 -13
- data/lib/active_record/nested_attributes.rb +6 -6
- data/lib/active_record/persistence.rb +162 -133
- data/lib/active_record/query_cache.rb +22 -15
- data/lib/active_record/query_logs.rb +104 -52
- data/lib/active_record/query_logs_formatter.rb +17 -28
- data/lib/active_record/querying.rb +12 -12
- data/lib/active_record/railtie.rb +37 -32
- data/lib/active_record/railties/controller_runtime.rb +11 -6
- data/lib/active_record/railties/databases.rake +26 -37
- data/lib/active_record/railties/job_checkpoints.rb +15 -0
- data/lib/active_record/railties/job_runtime.rb +10 -11
- data/lib/active_record/reflection.rb +53 -21
- data/lib/active_record/relation/batches/batch_enumerator.rb +4 -3
- data/lib/active_record/relation/batches.rb +147 -73
- data/lib/active_record/relation/calculations.rb +80 -63
- data/lib/active_record/relation/delegation.rb +25 -15
- data/lib/active_record/relation/finder_methods.rb +54 -37
- data/lib/active_record/relation/merger.rb +8 -8
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +11 -9
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +8 -8
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +4 -3
- data/lib/active_record/relation/predicate_builder.rb +22 -7
- data/lib/active_record/relation/query_attribute.rb +4 -2
- data/lib/active_record/relation/query_methods.rb +156 -95
- data/lib/active_record/relation/spawn_methods.rb +7 -7
- data/lib/active_record/relation/where_clause.rb +10 -11
- data/lib/active_record/relation.rb +122 -80
- data/lib/active_record/result.rb +109 -24
- data/lib/active_record/runtime_registry.rb +42 -58
- data/lib/active_record/sanitization.rb +9 -6
- data/lib/active_record/schema_dumper.rb +47 -22
- data/lib/active_record/schema_migration.rb +2 -1
- data/lib/active_record/scoping/named.rb +5 -2
- data/lib/active_record/scoping.rb +0 -1
- data/lib/active_record/secure_token.rb +3 -3
- data/lib/active_record/signed_id.rb +47 -18
- data/lib/active_record/statement_cache.rb +24 -20
- data/lib/active_record/store.rb +51 -22
- data/lib/active_record/structured_event_subscriber.rb +85 -0
- data/lib/active_record/table_metadata.rb +6 -23
- data/lib/active_record/tasks/abstract_tasks.rb +76 -0
- data/lib/active_record/tasks/database_tasks.rb +85 -85
- data/lib/active_record/tasks/mysql_database_tasks.rb +3 -42
- data/lib/active_record/tasks/postgresql_database_tasks.rb +14 -40
- data/lib/active_record/tasks/sqlite_database_tasks.rb +16 -28
- data/lib/active_record/test_databases.rb +14 -4
- data/lib/active_record/test_fixtures.rb +39 -2
- data/lib/active_record/testing/query_assertions.rb +8 -2
- data/lib/active_record/timestamp.rb +4 -2
- data/lib/active_record/token_for.rb +1 -1
- data/lib/active_record/transaction.rb +2 -5
- data/lib/active_record/transactions.rb +39 -16
- data/lib/active_record/type/hash_lookup_type_map.rb +2 -1
- data/lib/active_record/type/internal/timezone.rb +7 -0
- data/lib/active_record/type/json.rb +15 -2
- data/lib/active_record/type/serialized.rb +11 -4
- data/lib/active_record/type/type_map.rb +1 -1
- data/lib/active_record/type_caster/connection.rb +2 -1
- data/lib/active_record/validations/associated.rb +1 -1
- data/lib/active_record/validations/uniqueness.rb +8 -8
- data/lib/active_record.rb +85 -50
- data/lib/arel/alias_predication.rb +2 -0
- data/lib/arel/collectors/bind.rb +2 -2
- data/lib/arel/collectors/sql_string.rb +1 -1
- data/lib/arel/collectors/substitute_binds.rb +2 -2
- data/lib/arel/crud.rb +8 -11
- data/lib/arel/delete_manager.rb +5 -0
- data/lib/arel/nodes/binary.rb +1 -1
- data/lib/arel/nodes/count.rb +2 -2
- data/lib/arel/nodes/delete_statement.rb +4 -2
- data/lib/arel/nodes/function.rb +4 -10
- data/lib/arel/nodes/named_function.rb +2 -2
- data/lib/arel/nodes/node.rb +2 -2
- data/lib/arel/nodes/sql_literal.rb +1 -1
- data/lib/arel/nodes/update_statement.rb +4 -2
- data/lib/arel/nodes.rb +0 -2
- data/lib/arel/select_manager.rb +13 -4
- data/lib/arel/table.rb +3 -7
- data/lib/arel/update_manager.rb +5 -0
- data/lib/arel/visitors/dot.rb +2 -3
- data/lib/arel/visitors/postgresql.rb +55 -0
- data/lib/arel/visitors/sqlite.rb +55 -8
- data/lib/arel/visitors/to_sql.rb +6 -22
- data/lib/arel.rb +3 -1
- data/lib/rails/generators/active_record/application_record/USAGE +1 -1
- metadata +17 -17
- data/lib/active_record/explain_subscriber.rb +0 -34
- data/lib/active_record/normalization.rb +0 -163
- data/lib/active_record/relation/record_fetch_warning.rb +0 -52
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "thread"
|
|
4
3
|
require "concurrent/map"
|
|
5
4
|
|
|
6
5
|
module ActiveRecord
|
|
@@ -55,19 +54,22 @@ module ActiveRecord
|
|
|
55
54
|
# about the model. The model needs to pass a connection specification name to the handler,
|
|
56
55
|
# in order to look up the correct connection pool.
|
|
57
56
|
class ConnectionHandler
|
|
58
|
-
class
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
def initialize(name)
|
|
57
|
+
class ConnectionDescriptor # :nodoc:
|
|
58
|
+
def initialize(name, primary = false)
|
|
62
59
|
@name = name
|
|
60
|
+
@primary = primary
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def name
|
|
64
|
+
primary_class? ? "ActiveRecord::Base" : @name
|
|
63
65
|
end
|
|
64
66
|
|
|
65
67
|
def primary_class?
|
|
66
|
-
|
|
68
|
+
@primary
|
|
67
69
|
end
|
|
68
70
|
|
|
69
71
|
def current_preventing_writes
|
|
70
|
-
|
|
72
|
+
ActiveRecord::Base.preventing_writes?(@name)
|
|
71
73
|
end
|
|
72
74
|
end
|
|
73
75
|
|
|
@@ -116,7 +118,7 @@ module ActiveRecord
|
|
|
116
118
|
pool_config = resolve_pool_config(config, owner_name, role, shard)
|
|
117
119
|
db_config = pool_config.db_config
|
|
118
120
|
|
|
119
|
-
pool_manager = set_pool_manager(pool_config.
|
|
121
|
+
pool_manager = set_pool_manager(pool_config.connection_descriptor)
|
|
120
122
|
|
|
121
123
|
# If there is an existing pool with the same values as the pool_config
|
|
122
124
|
# don't remove the connection. Connections should only be removed if we are
|
|
@@ -128,8 +130,8 @@ module ActiveRecord
|
|
|
128
130
|
# Update the pool_config's connection class if it differs. This is used
|
|
129
131
|
# for ensuring that ActiveRecord::Base and the primary_abstract_class use
|
|
130
132
|
# the same pool. Without this granular swapping will not work correctly.
|
|
131
|
-
if owner_name.primary_class? && (existing_pool_config.
|
|
132
|
-
existing_pool_config.
|
|
133
|
+
if owner_name.primary_class? && (existing_pool_config.connection_descriptor != owner_name)
|
|
134
|
+
existing_pool_config.connection_descriptor = owner_name
|
|
133
135
|
end
|
|
134
136
|
|
|
135
137
|
existing_pool_config.pool
|
|
@@ -138,7 +140,7 @@ module ActiveRecord
|
|
|
138
140
|
pool_manager.set_pool_config(role, shard, pool_config)
|
|
139
141
|
|
|
140
142
|
payload = {
|
|
141
|
-
connection_name: pool_config.
|
|
143
|
+
connection_name: pool_config.connection_descriptor.name,
|
|
142
144
|
role: role,
|
|
143
145
|
shard: shard,
|
|
144
146
|
config: db_config.configuration_hash
|
|
@@ -156,9 +158,7 @@ module ActiveRecord
|
|
|
156
158
|
each_connection_pool(role).any?(&:active_connection?)
|
|
157
159
|
end
|
|
158
160
|
|
|
159
|
-
# Returns any connections in use by the current thread back to the pool
|
|
160
|
-
# and also returns connections to the pool cached by threads that are no
|
|
161
|
-
# longer alive.
|
|
161
|
+
# Returns any connections in use by the current thread back to the pool.
|
|
162
162
|
def clear_active_connections!(role = nil)
|
|
163
163
|
each_connection_pool(role).each do |pool|
|
|
164
164
|
pool.release_connection
|
|
@@ -166,7 +166,7 @@ module ActiveRecord
|
|
|
166
166
|
end
|
|
167
167
|
end
|
|
168
168
|
|
|
169
|
-
# Clears
|
|
169
|
+
# Clears reloadable connection caches in all connection pools.
|
|
170
170
|
#
|
|
171
171
|
# See ConnectionPool#clear_reloadable_connections! for details.
|
|
172
172
|
def clear_reloadable_connections!(role = nil)
|
|
@@ -210,18 +210,25 @@ module ActiveRecord
|
|
|
210
210
|
# This makes retrieving the connection pool O(1) once the process is warm.
|
|
211
211
|
# When a connection is established or removed, we invalidate the cache.
|
|
212
212
|
def retrieve_connection_pool(connection_name, role: ActiveRecord::Base.current_role, shard: ActiveRecord::Base.current_shard, strict: false)
|
|
213
|
-
|
|
213
|
+
pool_manager = get_pool_manager(connection_name)
|
|
214
|
+
pool = pool_manager&.get_pool_config(role, shard)&.pool
|
|
214
215
|
|
|
215
216
|
if strict && !pool
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
217
|
+
selector = [
|
|
218
|
+
("'#{shard}' shard" unless shard == ActiveRecord::Base.default_shard),
|
|
219
|
+
("'#{role}' role" unless role == ActiveRecord::Base.default_role),
|
|
220
|
+
].compact.join(" and ")
|
|
221
|
+
|
|
222
|
+
selector = [
|
|
223
|
+
(connection_name unless connection_name == "ActiveRecord::Base"),
|
|
224
|
+
selector.presence,
|
|
225
|
+
].compact.join(" with ")
|
|
226
|
+
|
|
227
|
+
selector = " for #{selector}" if selector.present?
|
|
228
|
+
|
|
229
|
+
message = "No database connection defined#{selector}."
|
|
223
230
|
|
|
224
|
-
raise
|
|
231
|
+
raise ConnectionNotDefined.new(message, connection_name: connection_name, shard: shard, role: role)
|
|
225
232
|
end
|
|
226
233
|
|
|
227
234
|
pool
|
|
@@ -236,8 +243,8 @@ module ActiveRecord
|
|
|
236
243
|
end
|
|
237
244
|
|
|
238
245
|
# Get the existing pool manager or initialize and assign a new one.
|
|
239
|
-
def set_pool_manager(
|
|
240
|
-
connection_name_to_pool_manager[
|
|
246
|
+
def set_pool_manager(connection_descriptor)
|
|
247
|
+
connection_name_to_pool_manager[connection_descriptor.name] ||= PoolManager.new
|
|
241
248
|
end
|
|
242
249
|
|
|
243
250
|
def pool_managers
|
|
@@ -272,9 +279,9 @@ module ActiveRecord
|
|
|
272
279
|
|
|
273
280
|
def determine_owner_name(owner_name, config)
|
|
274
281
|
if owner_name.is_a?(String) || owner_name.is_a?(Symbol)
|
|
275
|
-
|
|
282
|
+
ConnectionDescriptor.new(owner_name.to_s)
|
|
276
283
|
elsif config.is_a?(Symbol)
|
|
277
|
-
|
|
284
|
+
ConnectionDescriptor.new(config.to_s)
|
|
278
285
|
else
|
|
279
286
|
owner_name
|
|
280
287
|
end
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "thread"
|
|
4
3
|
require "monitor"
|
|
5
4
|
|
|
6
5
|
module ActiveRecord
|
|
@@ -41,6 +40,14 @@ module ActiveRecord
|
|
|
41
40
|
end
|
|
42
41
|
end
|
|
43
42
|
|
|
43
|
+
# Add +element+ to the back of the queue. Never blocks.
|
|
44
|
+
def add_back(element)
|
|
45
|
+
synchronize do
|
|
46
|
+
@queue.unshift element
|
|
47
|
+
@cond.signal
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
44
51
|
# If +element+ is in the queue, remove and return it, or +nil+.
|
|
45
52
|
def delete(element)
|
|
46
53
|
synchronize do
|
|
@@ -55,6 +62,13 @@ module ActiveRecord
|
|
|
55
62
|
end
|
|
56
63
|
end
|
|
57
64
|
|
|
65
|
+
# Number of elements in the queue.
|
|
66
|
+
def size
|
|
67
|
+
synchronize do
|
|
68
|
+
@queue.size
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
58
72
|
# Remove the head of the queue.
|
|
59
73
|
#
|
|
60
74
|
# If +timeout+ is not given, remove and return the head of the
|
|
@@ -115,9 +129,7 @@ module ActiveRecord
|
|
|
115
129
|
t0 = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
116
130
|
elapsed = 0
|
|
117
131
|
loop do
|
|
118
|
-
|
|
119
|
-
@cond.wait(timeout - elapsed)
|
|
120
|
-
end
|
|
132
|
+
@cond.wait(timeout - elapsed)
|
|
121
133
|
|
|
122
134
|
return remove if any?
|
|
123
135
|
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "thread"
|
|
4
3
|
require "weakref"
|
|
5
4
|
|
|
6
5
|
module ActiveRecord
|
|
@@ -8,12 +7,29 @@ module ActiveRecord
|
|
|
8
7
|
class ConnectionPool
|
|
9
8
|
# = Active Record Connection Pool \Reaper
|
|
10
9
|
#
|
|
11
|
-
#
|
|
12
|
-
#
|
|
13
|
-
# the connection pool.
|
|
10
|
+
# The reaper is a singleton that exists in the background of the process
|
|
11
|
+
# and is responsible for general maintenance of all the connection pools.
|
|
14
12
|
#
|
|
15
|
-
#
|
|
16
|
-
#
|
|
13
|
+
# It will reclaim connections that are leased to now-dead threads,
|
|
14
|
+
# ensuring that a bad thread can't leak a pool slot forever. By definition,
|
|
15
|
+
# this involves touching currently-leased connections, but that is safe
|
|
16
|
+
# because the owning thread is known to be dead.
|
|
17
|
+
#
|
|
18
|
+
# Beyond that, it manages the health of available / unleased connections:
|
|
19
|
+
# * retiring connections that have been idle[1] for too long
|
|
20
|
+
# * creating occasional activity on inactive[1] connections
|
|
21
|
+
# * keeping the pool prepopulated up to its minimum size
|
|
22
|
+
# * proactively connecting to the target database from any pooled
|
|
23
|
+
# connections that had lazily deferred that step
|
|
24
|
+
# * resetting or replacing connections that are known to be broken
|
|
25
|
+
#
|
|
26
|
+
#
|
|
27
|
+
# [1]: "idle" and "inactive" here distinguish between connections that
|
|
28
|
+
# have not been requested by the application in a while (idle) and those
|
|
29
|
+
# that have not spoken to their remote server in a while (inactive). The
|
|
30
|
+
# former is a desirable opportunity to reduce our connection count
|
|
31
|
+
# (`idle_timeout`); the latter is a risk that the server or a firewall may
|
|
32
|
+
# drop a connection we still anticipate using (avoided by `keepalive`).
|
|
17
33
|
class Reaper
|
|
18
34
|
attr_reader :pool, :frequency
|
|
19
35
|
|
|
@@ -37,6 +53,15 @@ module ActiveRecord
|
|
|
37
53
|
end
|
|
38
54
|
end
|
|
39
55
|
|
|
56
|
+
def pools(refs = nil) # :nodoc:
|
|
57
|
+
refs ||= @mutex.synchronize { @pools.values.flatten(1) }
|
|
58
|
+
|
|
59
|
+
refs.filter_map do |ref|
|
|
60
|
+
ref.__getobj__ if ref.weakref_alive?
|
|
61
|
+
rescue WeakRef::RefError
|
|
62
|
+
end.select(&:maintainable?)
|
|
63
|
+
end
|
|
64
|
+
|
|
40
65
|
private
|
|
41
66
|
def spawn_thread(frequency)
|
|
42
67
|
Thread.new(frequency) do |t|
|
|
@@ -47,23 +72,36 @@ module ActiveRecord
|
|
|
47
72
|
running = true
|
|
48
73
|
while running
|
|
49
74
|
sleep t
|
|
75
|
+
|
|
76
|
+
refs = nil
|
|
77
|
+
|
|
50
78
|
@mutex.synchronize do
|
|
51
|
-
@pools[frequency]
|
|
52
|
-
pool.weakref_alive? && !pool.discarded?
|
|
53
|
-
end
|
|
79
|
+
refs = @pools[frequency]
|
|
54
80
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
p.flush
|
|
81
|
+
refs.select! do |pool|
|
|
82
|
+
pool.weakref_alive? && !pool.discarded?
|
|
58
83
|
rescue WeakRef::RefError
|
|
59
84
|
end
|
|
60
85
|
|
|
61
|
-
if
|
|
86
|
+
if refs.empty?
|
|
62
87
|
@pools.delete(frequency)
|
|
63
88
|
@threads.delete(frequency)
|
|
64
89
|
running = false
|
|
65
90
|
end
|
|
66
91
|
end
|
|
92
|
+
|
|
93
|
+
if running
|
|
94
|
+
pools(refs).each do |pool|
|
|
95
|
+
pool.reaper_lock do
|
|
96
|
+
pool.reap
|
|
97
|
+
pool.flush
|
|
98
|
+
pool.prepopulate
|
|
99
|
+
pool.retire_old_connections
|
|
100
|
+
pool.keep_alive
|
|
101
|
+
pool.preconnect
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
67
105
|
end
|
|
68
106
|
end
|
|
69
107
|
end
|