sbmt-outbox 6.16.0 → 6.17.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 86044914d6babd961a882ecfd9394875e0b67f74a2b92f44db48480bb5096448
4
- data.tar.gz: 3ae09e5801c2dcacc9096bae5c2428f2c57445394dd5a3d036c58b1fa63121d2
3
+ metadata.gz: ad4860726f28975383df9bf2d522e994f80644dfe9a3d3476cf517ee90443bf4
4
+ data.tar.gz: 16925e325aeab7dc040a46940e34c7318f526bb39c633fb3dd7be53d187d6e96
5
5
  SHA512:
6
- metadata.gz: 9f180114bce2540c91f6c942195fa59c51bcfea67bd984ee5b7db19fd95653933492ce30f7890833e879469b2bb08ca5bcfad2b5a8efa8221eae904b2839a42f
7
- data.tar.gz: e9aeadbc87d76a0f86c7b7c9ddad157c45851e3941901bf4ff249c116a7d32827645157ed644709ba59756569af0d9637e0b66c0c9b0c10937ba6b5878ac740d
6
+ metadata.gz: c4a2fb0a085133946fa0a741545ab76f173b096d2c817deaac12511207f695e93e15c40fdda475ac747ccaf79c8bb9895c73ce5594afc7e71db7fc0a4427ebb4
7
+ data.tar.gz: 6baa8c4f01d13859ba3879de9c8f9a749251331045b0df35aee4a0dc52660e136a46653db416e5d9eaf78711864a79da6e3f788711b5474b46be1f62cb505d15
data/README.md CHANGED
@@ -273,6 +273,7 @@ default: &default
273
273
  delivered_min_retention_period: PT1H #optional, default: PT1H, for statuses: delivered, retention period for delivered items, https://en.wikipedia.org/wiki/ISO_8601#Durations
274
274
  deletion_batch_size: 1_000 #optional, default: 1_000
275
275
  deletion_sleep_time: 0.5 #optional, default: 0.5
276
+ deletion_time_window: PT4H #optional, default: PT4H, for statuses: delivered, retention period for delivered items, https://en.wikipedia.org/wiki/ISO_8601#Durations
276
277
  max_retries: 3 # default 0, the number of retries before the item will be marked as failed
277
278
  strict_order: false # optional, default
278
279
  transports: # transports section
@@ -353,6 +354,7 @@ inbox_items: # inbox items section
353
354
  delivered_min_retention_period: PT1H #optional, default: PT1H, for statuses: delivered, retention period for delivered items, https://en.wikipedia.org/wiki/ISO_8601#Durations
354
355
  deletion_batch_size: 1_000 #optional, default: 1_000
355
356
  deletion_sleep_time: 0.5 #optional, default: 0.5
357
+ deletion_time_window: PT4H #optional, default: PT4H, for statuses: delivered, retention period for delivered items, https://en.wikipedia.org/wiki/ISO_8601#Durations
356
358
  max_retries: 3 # default 0, the number of retries before the item will be marked as failed
357
359
  transports: # transports section
358
360
  import_order: # underscored transport class name
@@ -102,45 +102,50 @@ module Sbmt
102
102
  # SELECT "items"."id"
103
103
  # FROM "items"
104
104
  # WHERE (
105
- # "items"."status" = 1 AND "items"."created_at" < '2023-05-01 00:00:00'
105
+ # "items"."status" IN (2) AND "items"."created_at" BETWEEN "2025-01-29 12:18:32.917836" AND "2025-01-29 12:18:32.927596" LIMIT 1000
106
106
  # )
107
- # LIMIT 1000
108
107
  # )
109
108
  def postgres_delete_in_batches(waterline_failed, waterline_delivered)
110
- table = item_class.arel_table
111
-
112
109
  status_delivered = item_class.statuses[:delivered]
113
110
  status_failed_discarded = item_class.statuses.values_at(:failed, :discarded)
114
111
 
115
- delete_items_in_batches(table, table[:status].eq(status_delivered).and(table[:created_at].lt(waterline_delivered)))
116
- delete_items_in_batches(table, table[:status].in(status_failed_discarded).and(table[:created_at].lt(waterline_failed)))
112
+ delete_items_in_batches_with_between(waterline_delivered, status_delivered)
113
+ delete_items_in_batches_with_between(waterline_failed, status_failed_discarded)
117
114
  end
118
115
 
119
- def delete_items_in_batches(table, condition)
120
- subquery = table
121
- .project(table[:id])
122
- .where(condition)
123
- .take(item_class.config.deletion_batch_size)
124
-
125
- delete_statement = Arel::Nodes::DeleteStatement.new
126
- delete_statement.relation = table
127
- delete_statement.wheres = [table[:id].in(subquery)]
116
+ def delete_items_in_batches_with_between(waterline, statuses)
117
+ table = item_class.arel_table
118
+ batch_size = item_class.config.deletion_batch_size
119
+ time_window = item_class.config.deletion_time_window
120
+ min_date = item_class.where(table[:status].in(statuses)).minimum(:created_at)
128
121
  deleted_count = nil
129
122
 
130
- loop do
131
- track_deleted_latency do
132
- deleted_count = item_class
133
- .connection
134
- .execute(delete_statement.to_sql)
135
- .cmd_tuples
136
- end
123
+ while min_date && min_date < waterline
124
+ max_date = [min_date + time_window, waterline].min
125
+
126
+ loop do
127
+ subquery = table
128
+ .project(table[:id])
129
+ .where(table[:status].in(statuses))
130
+ .where(table[:created_at].between(min_date..max_date))
131
+ .take(batch_size)
132
+
133
+ delete_statement = Arel::Nodes::DeleteStatement.new
134
+ delete_statement.relation = table
135
+ delete_statement.wheres = [table[:id].in(subquery)]
136
+
137
+ track_deleted_latency do
138
+ deleted_count = item_class.connection.execute(delete_statement.to_sql).cmd_tuples
139
+ end
137
140
 
138
- track_deleted_counter(deleted_count)
141
+ track_deleted_counter(deleted_count)
139
142
 
140
- logger.log_info("Deleted #{deleted_count} #{box_type} items for #{box_name} items")
141
- break if deleted_count == 0
142
- lock_timer.checkpoint!
143
- sleep(item_class.config.deletion_sleep_time)
143
+ logger.log_info("Deleted #{deleted_count} #{box_type} items for #{box_name} between #{min_date} and #{max_date}")
144
+ break if deleted_count < batch_size
145
+ lock_timer.checkpoint!
146
+ sleep(item_class.config.deletion_sleep_time) if deleted_count > 0
147
+ end
148
+ min_date = max_date
144
149
  end
145
150
  end
146
151
 
@@ -154,37 +159,43 @@ module Sbmt
154
159
  # This approach doesn't require a subquery, making it more straightforward.
155
160
  #
156
161
  # Example SQL generated for deletion:
157
- # DELETE FROM `items`
162
+ # DELETE FROM "items"
158
163
  # WHERE (
159
- # `items`.`status` = 1 AND `items`.`created_at` < '2023-05-01 00:00:00'
164
+ # "items"."status" IN (2) AND "items"."created_at" BETWEEN "2024-12-29 18:34:25.369234" AND "2024-12-29 22:34:25.369234" LIMIT 1000
160
165
  # )
161
- # LIMIT 1000
162
166
  def mysql_delete_in_batches(waterline_failed, waterline_delivered)
163
167
  status_delivered = item_class.statuses[:delivered]
164
168
  status_failed_discarded = [item_class.statuses.values_at(:failed, :discarded)]
165
169
 
166
- delete_items_in_batches_mysql(
167
- item_class.where(status: status_delivered, created_at: ...waterline_delivered)
168
- )
169
- delete_items_in_batches_mysql(
170
- item_class.where(status: status_failed_discarded).where(created_at: ...waterline_failed)
171
- )
170
+ delete_items_in_batches_with_between_mysql(waterline_delivered, status_delivered)
171
+ delete_items_in_batches_with_between_mysql(waterline_failed, status_failed_discarded)
172
172
  end
173
173
 
174
- def delete_items_in_batches_mysql(query)
174
+ def delete_items_in_batches_with_between_mysql(waterline, statuses)
175
+ batch_size = item_class.config.deletion_batch_size
176
+ time_window = item_class.config.deletion_time_window
177
+ min_date = item_class.where(status: statuses).minimum(:created_at)
175
178
  deleted_count = nil
176
179
 
177
- loop do
178
- track_deleted_latency do
179
- deleted_count = query.limit(item_class.config.deletion_batch_size).delete_all
180
- end
180
+ while min_date && min_date < waterline
181
+ max_date = [min_date + time_window, waterline].min
182
+
183
+ loop do
184
+ track_deleted_latency do
185
+ deleted_count = item_class
186
+ .where(status: statuses, created_at: min_date..max_date)
187
+ .limit(batch_size)
188
+ .delete_all
189
+ end
181
190
 
182
- track_deleted_counter(deleted_count)
191
+ track_deleted_counter(deleted_count)
183
192
 
184
- logger.log_info("Deleted #{deleted_count} #{box_type} items for #{box_name} items")
185
- break if deleted_count == 0
186
- lock_timer.checkpoint!
187
- sleep(item_class.config.deletion_sleep_time)
193
+ logger.log_info("Deleted #{deleted_count} #{box_type} items for #{box_name} between #{min_date} and #{max_date}")
194
+ break if deleted_count < batch_size
195
+ lock_timer.checkpoint!
196
+ sleep(item_class.config.deletion_sleep_time) if deleted_count > 0
197
+ end
198
+ min_date = max_date
188
199
  end
189
200
  end
190
201
 
@@ -60,6 +60,10 @@ module Sbmt
60
60
  @delivered_min_retention_period ||= ActiveSupport::Duration.parse(options[:delivered_min_retention_period] || "PT1H")
61
61
  end
62
62
 
63
+ def deletion_time_window
64
+ @deletion_time_window ||= ActiveSupport::Duration.parse(options[:deletion_time_window] || "PT4H")
65
+ end
66
+
63
67
  def max_retries
64
68
  @max_retries ||= (options[:max_retries] || 0).to_i
65
69
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Sbmt
4
4
  module Outbox
5
- VERSION = "6.16.0"
5
+ VERSION = "6.17.0"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sbmt-outbox
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.16.0
4
+ version: 6.17.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sbermarket Ruby-Platform Team
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-01-28 00:00:00.000000000 Z
11
+ date: 2025-02-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: connection_pool
@@ -629,7 +629,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
629
629
  - !ruby/object:Gem::Version
630
630
  version: '0'
631
631
  requirements: []
632
- rubygems_version: 3.1.6
632
+ rubygems_version: 3.5.21
633
633
  signing_key:
634
634
  specification_version: 4
635
635
  summary: Outbox service