sbmt-outbox 6.16.0 → 6.17.0

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 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