Skip to content

Commit 246bac4

Browse files
authored
Merge pull request rails#42605 from Tonkpils/tonkpils/revert-disable-automatic-write-protection
Revert "Disable automatic write protection on replicas"
2 parents 5a26648 + 69bc201 commit 246bac4

11 files changed

+34
-38
lines changed

activerecord/CHANGELOG.md

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,6 @@
2222

2323
*Jorge Manrubia*
2424

25-
* Disable automatic write protection on replicas.
26-
27-
Write protection is no longer automatically enabled for replicas.
28-
You can manually prevent writes in your app with
29-
`while_preventing_writes`. To automatically disable all writes on
30-
your replica, configure the database user you are using to connect
31-
to your replica to prevent writes. How you configure this is
32-
specific to which database adapter you are using, but it usually
33-
involves only granting the database user permission to do `SELECT`
34-
queries.
35-
36-
*Adam Hess*
37-
3825
* The MySQL adapter now cast numbers and booleans bind parameters to to string for safety reasons.
3926

4027
When comparing a string and a number in a query, MySQL convert the string to a number. So for

activerecord/lib/active_record/connection_adapters/abstract_adapter.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,12 +131,15 @@ def use_metadata_table?
131131

132132
# Determines whether writes are currently being prevented.
133133
#
134+
# Returns true if the connection is a replica.
135+
#
134136
# If the application is using legacy handling, returns
135137
# true if +connection_handler.prevent_writes+ is set.
136138
#
137139
# If the application is using the new connection handling
138140
# will return true based on +current_preventing_writes+.
139141
def preventing_writes?
142+
return true if replica?
140143
return ActiveRecord::Base.connection_handler.prevent_writes if ActiveRecord.legacy_connection_handling
141144
return false if connection_klass.nil?
142145

activerecord/lib/active_record/connection_handling.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,8 @@ def connected_to_many(*classes, role:, shard: nil, prevent_writes: false)
184184
raise NotImplementedError, "connected_to_many can only be called on ActiveRecord::Base."
185185
end
186186

187+
prevent_writes = true if role == ActiveRecord.reading_role
188+
187189
connected_to_stack << { role: role, shard: shard, prevent_writes: prevent_writes, klasses: classes }
188190
yield
189191
ensure
@@ -202,6 +204,8 @@ def connecting_to(role: default_role, shard: default_shard, prevent_writes: fals
202204
raise NotImplementedError, "`connecting_to` is not available with `legacy_connection_handling`."
203205
end
204206

207+
prevent_writes = true if role == ActiveRecord.reading_role
208+
205209
self.connected_to_stack << { role: role, shard: shard, prevent_writes: prevent_writes, klasses: [self] }
206210
end
207211

@@ -352,6 +356,8 @@ def with_handler(handler_key, &blk)
352356
end
353357

354358
def with_role_and_shard(role, shard, prevent_writes)
359+
prevent_writes = true if role == ActiveRecord.reading_role
360+
355361
if ActiveRecord.legacy_connection_handling
356362
with_handler(role.to_sym) do
357363
connection_handler.while_preventing_writes(prevent_writes) do

activerecord/lib/active_record/middleware/database_selector/resolver.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ def read_from_primary(&blk)
5858
end
5959

6060
def read_from_replica(&blk)
61-
ActiveRecord::Base.connected_to(role: ActiveRecord.reading_role) do
61+
ActiveRecord::Base.connected_to(role: ActiveRecord.reading_role, prevent_writes: true) do
6262
instrumenter.instrument("database_selector.active_record.read_from_replica") do
6363
yield
6464
end

activerecord/test/cases/base_test.rb

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1721,7 +1721,7 @@ def test_protected_environments_are_stored_as_an_array_of_string
17211721
SecondAbstractClass.connecting_to(role: :reading)
17221722

17231723
assert SecondAbstractClass.connected_to?(role: :reading)
1724-
assert_not SecondAbstractClass.current_preventing_writes
1724+
assert SecondAbstractClass.current_preventing_writes
17251725
ensure
17261726
ActiveRecord::Base.connected_to_stack.pop
17271727
end
@@ -1777,24 +1777,24 @@ def test_protected_environments_are_stored_as_an_array_of_string
17771777
end
17781778
end
17791779

1780-
test "#connected_to_many does not sets prevent_writes if role is reading" do
1780+
test "#connected_to_many sets prevent_writes if role is reading" do
17811781
ActiveRecord::Base.connected_to_many([SecondAbstractClass], role: :reading) do
1782-
assert_not SecondAbstractClass.current_preventing_writes
1782+
assert SecondAbstractClass.current_preventing_writes
17831783
assert_not ActiveRecord::Base.current_preventing_writes
17841784
end
17851785
end
17861786

1787-
test "#connected_to_many with a single argument for classes does not set prevent_writes" do
1787+
test "#connected_to_many with a single argument for classes" do
17881788
ActiveRecord::Base.connected_to_many(SecondAbstractClass, role: :reading) do
1789-
assert_not SecondAbstractClass.current_preventing_writes
1789+
assert SecondAbstractClass.current_preventing_writes
17901790
assert_not ActiveRecord::Base.current_preventing_writes
17911791
end
17921792
end
17931793

1794-
test "#connected_to_many with a multiple classes without brackets does not prevent_writes" do
1794+
test "#connected_to_many with a multiple classes without brackets works" do
17951795
ActiveRecord::Base.connected_to_many(FirstAbstractClass, SecondAbstractClass, role: :reading) do
1796-
assert_not FirstAbstractClass.current_preventing_writes
1797-
assert_not SecondAbstractClass.current_preventing_writes
1796+
assert FirstAbstractClass.current_preventing_writes
1797+
assert SecondAbstractClass.current_preventing_writes
17981798
assert_not ActiveRecord::Base.current_preventing_writes
17991799
end
18001800
end

activerecord/test/cases/connection_adapters/connection_handlers_multi_db_test.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ def test_switching_connections_via_handler
130130
assert_equal :reading, ActiveRecord::Base.current_role
131131
assert ActiveRecord::Base.connected_to?(role: :reading)
132132
assert_not ActiveRecord::Base.connected_to?(role: :writing)
133-
assert_not_predicate ActiveRecord::Base.connection, :preventing_writes?
133+
assert_predicate ActiveRecord::Base.connection, :preventing_writes?
134134
end
135135

136136
ActiveRecord::Base.connected_to(role: :writing) do

activerecord/test/cases/connection_adapters/connection_handlers_sharding_db_test.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ def test_switching_connections_via_handler
135135
assert_not ActiveRecord::Base.connected_to?(role: :writing, shard: :default)
136136
assert_not ActiveRecord::Base.connected_to?(role: :writing, shard: :shard_one)
137137
assert_not ActiveRecord::Base.connected_to?(role: :reading, shard: :shard_one)
138-
assert_not_predicate ActiveRecord::Base.connection, :preventing_writes?
138+
assert_predicate ActiveRecord::Base.connection, :preventing_writes?
139139
end
140140

141141
ActiveRecord::Base.connected_to(role: :writing, shard: :default) do
@@ -153,7 +153,7 @@ def test_switching_connections_via_handler
153153
assert_not ActiveRecord::Base.connected_to?(role: :writing, shard: :shard_one)
154154
assert_not ActiveRecord::Base.connected_to?(role: :writing, shard: :default)
155155
assert_not ActiveRecord::Base.connected_to?(role: :reading, shard: :default)
156-
assert_not_predicate ActiveRecord::Base.connection, :preventing_writes?
156+
assert_predicate ActiveRecord::Base.connection, :preventing_writes?
157157
end
158158

159159
ActiveRecord::Base.connected_to(role: :writing, shard: :shard_one) do

activerecord/test/cases/connection_adapters/connection_swapping_nested_test.rb

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -391,23 +391,23 @@ def test_prevent_writes_can_be_changed_granularly
391391

392392
# Switch only primary to reading
393393
PrimaryBase.connected_to(role: :reading) do
394-
assert_not_predicate PrimaryBase.connection, :preventing_writes?
394+
assert_predicate PrimaryBase.connection, :preventing_writes?
395395
assert_not_predicate SecondaryBase.connection, :preventing_writes?
396396

397397
# Switch global to reading
398398
ActiveRecord::Base.connected_to(role: :reading) do
399-
assert_not_predicate PrimaryBase.connection, :preventing_writes?
400-
assert_not_predicate SecondaryBase.connection, :preventing_writes?
399+
assert_predicate PrimaryBase.connection, :preventing_writes?
400+
assert_predicate SecondaryBase.connection, :preventing_writes?
401401

402402
# Switch only secondary to writing
403403
SecondaryBase.connected_to(role: :writing) do
404-
assert_not_predicate PrimaryBase.connection, :preventing_writes?
404+
assert_predicate PrimaryBase.connection, :preventing_writes?
405405
assert_not_predicate SecondaryBase.connection, :preventing_writes?
406406
end
407407

408408
# Ensure restored to global reading
409-
assert_not_predicate PrimaryBase.connection, :preventing_writes?
410-
assert_not_predicate SecondaryBase.connection, :preventing_writes?
409+
assert_predicate PrimaryBase.connection, :preventing_writes?
410+
assert_predicate SecondaryBase.connection, :preventing_writes?
411411
end
412412

413413
# Switch everything to writing
@@ -416,7 +416,7 @@ def test_prevent_writes_can_be_changed_granularly
416416
assert_not_predicate SecondaryBase.connection, :preventing_writes?
417417
end
418418

419-
assert_not_predicate PrimaryBase.connection, :preventing_writes?
419+
assert_predicate PrimaryBase.connection, :preventing_writes?
420420
assert_not_predicate SecondaryBase.connection, :preventing_writes?
421421
end
422422

@@ -444,7 +444,7 @@ def test_application_record_prevent_writes_can_be_changed
444444
assert_not_predicate ApplicationRecord.connection, :preventing_writes?
445445

446446
ApplicationRecord.connected_to(role: :reading) do
447-
assert_not_predicate ApplicationRecord.connection, :preventing_writes?
447+
assert_predicate ApplicationRecord.connection, :preventing_writes?
448448
end
449449
end
450450
ensure

activerecord/test/cases/connection_adapters/legacy_connection_handlers_multi_db_test.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ def test_switching_connections_via_handler
180180
assert_equal :reading, ActiveRecord::Base.current_role
181181
assert ActiveRecord::Base.connected_to?(role: :reading)
182182
assert_not ActiveRecord::Base.connected_to?(role: :writing)
183-
assert_not_predicate ActiveRecord::Base.connection, :preventing_writes?
183+
assert_predicate ActiveRecord::Base.connection, :preventing_writes?
184184
end
185185

186186
ActiveRecord::Base.connected_to(role: :writing) do

activerecord/test/cases/connection_adapters/legacy_connection_handlers_sharding_db_test.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ def test_switching_connections_via_handler
150150
assert_not ActiveRecord::Base.connected_to?(role: :writing, shard: :default)
151151
assert_not ActiveRecord::Base.connected_to?(role: :writing, shard: :shard_one)
152152
assert_not ActiveRecord::Base.connected_to?(role: :reading, shard: :shard_one)
153-
assert_not_predicate ActiveRecord::Base.connection, :preventing_writes?
153+
assert_predicate ActiveRecord::Base.connection, :preventing_writes?
154154
end
155155

156156
ActiveRecord::Base.connected_to(role: :writing, shard: :default) do
@@ -172,7 +172,7 @@ def test_switching_connections_via_handler
172172
assert_not ActiveRecord::Base.connected_to?(role: :writing, shard: :shard_one)
173173
assert_not ActiveRecord::Base.connected_to?(role: :writing, shard: :default)
174174
assert_not ActiveRecord::Base.connected_to?(role: :reading, shard: :default)
175-
assert_not_predicate ActiveRecord::Base.connection, :preventing_writes?
175+
assert_predicate ActiveRecord::Base.connection, :preventing_writes?
176176
end
177177

178178
ActiveRecord::Base.connected_to(role: :writing, shard: :shard_one) do

0 commit comments

Comments
 (0)