33module Database
44 class OldRecordCleanup
55 class NoCurrentTimestampError < StandardError ; end
6- attr_reader :model , :days_ago , :keep_at_least_one_record , :keep_running_records , :keep_unprocessed_records
6+ attr_reader :model , :days_ago , :keep_at_least_one_record , :keep_running_records , :keep_unprocessed_records , :threshold_for_keeping_unprocessed_records
77
8- def initialize ( model , cutoff_age_in_days :, keep_at_least_one_record : false , keep_running_records : false , keep_unprocessed_records : false )
8+ def initialize ( model , cutoff_age_in_days :, keep_at_least_one_record : false , keep_running_records : false , keep_unprocessed_records : false ,
9+ threshold_for_keeping_unprocessed_records : nil )
910 @model = model
1011 @days_ago = cutoff_age_in_days
1112 @keep_at_least_one_record = keep_at_least_one_record
1213 @keep_running_records = keep_running_records
1314 @keep_unprocessed_records = keep_unprocessed_records
15+ @threshold_for_keeping_unprocessed_records = threshold_for_keeping_unprocessed_records
1416 end
1517
1618 def delete
@@ -97,16 +99,22 @@ def exclude_unprocessed_records(old_records)
9799
98100 return old_records unless consumer_model
99101
100- # Find the usage event record with the lowest ID
101- # of any that are referenced by a consumer
102- referenced_event = model .
103- join ( consumer_model . table_name . to_sym , last_processed_guid : :guid ) .
104- select ( Sequel . function ( :min , Sequel . qualify ( model . table_name , :id ) ) . as ( :min_id ) ) .
105- first
106-
107- return old_records if referenced_event [ :min_id ] . nil?
108-
109- old_records . where { id < referenced_event [ :min_id ] }
102+ if approximate_row_count ( model ) < threshold_for_keeping_unprocessed_records . to_i
103+ # Find the usage event record with the lowest ID
104+ # of any that are referenced by a consumer
105+ referenced_event = model .
106+ join ( consumer_model . table_name . to_sym , last_processed_guid : :guid ) .
107+ select ( Sequel . function ( :min , Sequel . qualify ( model . table_name , :id ) ) . as ( :min_id ) ) .
108+ first
109+
110+ return old_records if referenced_event [ :min_id ] . nil?
111+
112+ old_records . where { id < referenced_event [ :min_id ] }
113+ else
114+ # When above threshold, we don't exclude any records
115+ # Associated consumers will be automatically deleted by Sequel
116+ old_records
117+ end
110118 end
111119
112120 def registered_consumer_model ( model )
@@ -116,5 +124,27 @@ def registered_consumer_model(model)
116124
117125 false
118126 end
127+
128+ def approximate_row_count ( model )
129+ case model . db . database_type
130+ when :postgres
131+ result = model . db [ <<-SQL . squish
132+ SELECT reltuples::bigint AS estimate
133+ FROM pg_class
134+ WHERE relname = '#{ model . table_name } '
135+ SQL
136+ ] . first
137+ result [ :estimate ] . to_i
138+ when :mysql , :mysql2
139+ result = model . db [ <<-SQL . squish
140+ SELECT table_rows
141+ FROM information_schema.tables
142+ WHERE table_schema = DATABASE()
143+ AND table_name = '#{ model . table_name } '
144+ SQL
145+ ] . first
146+ result [ :table_rows ] . to_i
147+ end
148+ end
119149 end
120150end
0 commit comments