Skip to content

Commit 50baa7b

Browse files
committed
Fix dataset.truncate calls to handle MySQL FK constraints
The previous fix only addressed TableTruncator, but some code paths directly call dataset.truncate (e.g., purge_and_reseed_service_instances! and purge_and_reseed_started_apps!), which bypasses TableTruncator and fails with FK constraint violations on MySQL. Solution: Added truncate_with_fk_handling helper method to both repository classes that wraps dataset.truncate with the same db.synchronize + SET FOREIGN_KEY_CHECKS pattern to ensure all operations run on the same connection. This fixes the remaining MySQL 8.2 test failure in ServiceUsageEventRepository#purge_and_reseed_service_instances!
1 parent 16ab336 commit 50baa7b

File tree

2 files changed

+36
-2
lines changed

2 files changed

+36
-2
lines changed

app/repositories/app_usage_event_repository.rb

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ def create_from_build(build, state)
8888
end
8989

9090
def purge_and_reseed_started_apps!
91-
AppUsageEvent.dataset.truncate
91+
truncate_with_fk_handling(AppUsageEvent.dataset)
9292

9393
column_map = {
9494
app_name: :parent_app__name,
@@ -160,6 +160,22 @@ def delete_events_older_than(cutoff_age_in_days)
160160
def buildpack_name_for_app(app)
161161
CloudController::UrlSecretObfuscator.obfuscate(app.custom_buildpack_url || app.detected_buildpack_name)
162162
end
163+
164+
def truncate_with_fk_handling(dataset)
165+
db = dataset.db
166+
case db.database_type
167+
when :postgres
168+
dataset.truncate
169+
when :mysql
170+
# Use db.synchronize to ensure SET FOREIGN_KEY_CHECKS and TRUNCATE
171+
# run on the same connection. MySQL's FOREIGN_KEY_CHECKS is session-specific.
172+
db.synchronize do |conn|
173+
conn.query('SET FOREIGN_KEY_CHECKS = 0')
174+
conn.query("TRUNCATE TABLE #{dataset.first_source_table}")
175+
conn.query('SET FOREIGN_KEY_CHECKS = 1')
176+
end
177+
end
178+
end
163179
end
164180
end
165181
end

app/repositories/service_usage_event_repository.rb

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ def updated_event_from_service_instance(service_instance)
5454
end
5555

5656
def purge_and_reseed_service_instances!
57-
ServiceUsageEvent.dataset.truncate
57+
truncate_with_fk_handling(ServiceUsageEvent.dataset)
5858

5959
column_map = {
6060
# using service_instance guid because we need a unique guid for the service_usage_event. the database will not generate these for us.
@@ -94,6 +94,24 @@ def purge_and_reseed_service_instances!
9494
def delete_events_older_than(cutoff_age_in_days)
9595
Database::OldRecordCleanup.new(ServiceUsageEvent, cutoff_age_in_days: cutoff_age_in_days, keep_at_least_one_record: true, keep_running_records: true).delete
9696
end
97+
98+
private
99+
100+
def truncate_with_fk_handling(dataset)
101+
db = dataset.db
102+
case db.database_type
103+
when :postgres
104+
dataset.truncate
105+
when :mysql
106+
# Use db.synchronize to ensure SET FOREIGN_KEY_CHECKS and TRUNCATE
107+
# run on the same connection. MySQL's FOREIGN_KEY_CHECKS is session-specific.
108+
db.synchronize do |conn|
109+
conn.query('SET FOREIGN_KEY_CHECKS = 0')
110+
conn.query("TRUNCATE TABLE #{dataset.first_source_table}")
111+
conn.query('SET FOREIGN_KEY_CHECKS = 1')
112+
end
113+
end
114+
end
97115
end
98116
end
99117
end

0 commit comments

Comments
 (0)