sbmt-outbox 6.10.2 → 6.10.3
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 +4 -4
- data/app/jobs/sbmt/outbox/base_delete_stale_items_job.rb +90 -10
- data/lib/sbmt/outbox/version.rb +1 -1
- metadata +9 -23
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fabf75c06b0dea9c159918fe4496d3ffd47aa71caa1c364a6bfbef8c16a93494
|
4
|
+
data.tar.gz: d3c9b3a1bdfd55a0331b7e4fb971ac629c91b66cb952f4abb659e2b046a50187
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ff0b3cce600d2b1b82750036da4819d21715d05956491b0b9d7f056bb62800fc1e49b72ae069b978196c06671cd7157f0b0e78cb133e80819d16e191da5d533d
|
7
|
+
data.tar.gz: 99754cf0cb25199388a3dd3457c5d8225ff3a1cc6b8a16da2c67c69efd999268597be2aa2a2fba13a24e484e262ea59f382af2699da048143432cd97a74a3516
|
@@ -7,8 +7,8 @@ module Sbmt
|
|
7
7
|
class BaseDeleteStaleItemsJob < Outbox.active_job_base_class
|
8
8
|
MIN_RETENTION_PERIOD = 1.day
|
9
9
|
LOCK_TTL = 10_800_000
|
10
|
-
BATCH_SIZE =
|
11
|
-
SLEEP_TIME =
|
10
|
+
BATCH_SIZE = 1_000
|
11
|
+
SLEEP_TIME = 0.5
|
12
12
|
|
13
13
|
class << self
|
14
14
|
def enqueue
|
@@ -25,7 +25,7 @@ module Sbmt
|
|
25
25
|
delegate :config, :logger, to: "Sbmt::Outbox"
|
26
26
|
delegate :box_type, :box_name, to: :item_class
|
27
27
|
|
28
|
-
attr_accessor :item_class
|
28
|
+
attr_accessor :item_class, :lock_timer
|
29
29
|
|
30
30
|
def perform(item_class_name)
|
31
31
|
self.item_class = item_class_name.constantize
|
@@ -36,6 +36,7 @@ module Sbmt
|
|
36
36
|
Redis.new(config.redis)
|
37
37
|
end
|
38
38
|
|
39
|
+
self.lock_timer = Cutoff.new(LOCK_TTL / 1000)
|
39
40
|
lock_manager = Redlock::Client.new([client], retry_count: 0)
|
40
41
|
|
41
42
|
lock_manager.lock("#{self.class.name}:#{item_class_name}:lock", LOCK_TTL) do |locked|
|
@@ -51,6 +52,8 @@ module Sbmt
|
|
51
52
|
logger.log_info("Failed to acquire lock #{self.class.name}:#{item_class_name}")
|
52
53
|
end
|
53
54
|
end
|
55
|
+
rescue Cutoff::CutoffExceededError
|
56
|
+
logger.log_info("Lock timeout while processing #{item_class_name}")
|
54
57
|
end
|
55
58
|
|
56
59
|
private
|
@@ -64,17 +67,94 @@ module Sbmt
|
|
64
67
|
def delete_stale_items(waterline)
|
65
68
|
logger.log_info("Start deleting #{box_type} items for #{box_name} older than #{waterline}")
|
66
69
|
|
70
|
+
case database_type
|
71
|
+
when :postgresql
|
72
|
+
postgres_delete_in_batches(waterline)
|
73
|
+
when :mysql
|
74
|
+
mysql_delete_in_batches(waterline)
|
75
|
+
else
|
76
|
+
raise "Unsupported database type"
|
77
|
+
end
|
78
|
+
|
79
|
+
logger.log_info("Successfully deleted #{box_type} items for #{box_name} older than #{waterline}")
|
80
|
+
end
|
81
|
+
|
82
|
+
# Deletes stale items from PostgreSQL database in batches
|
83
|
+
#
|
84
|
+
# This method efficiently deletes items older than the given waterline
|
85
|
+
# using a subquery approach to avoid locking large portions of the table.
|
86
|
+
#
|
87
|
+
#
|
88
|
+
# Example SQL generated for deletion:
|
89
|
+
# DELETE FROM "items"
|
90
|
+
# WHERE "items"."id" IN (
|
91
|
+
# SELECT "items"."id"
|
92
|
+
# FROM "items"
|
93
|
+
# WHERE "items"."created_at" < '2023-05-01 00:00:00'
|
94
|
+
# LIMIT 1000
|
95
|
+
# )
|
96
|
+
def postgres_delete_in_batches(waterline)
|
97
|
+
table = item_class.arel_table
|
98
|
+
condition = table[:created_at].lt(waterline)
|
99
|
+
subquery = table
|
100
|
+
.project(table[:id])
|
101
|
+
.where(condition)
|
102
|
+
.take(BATCH_SIZE)
|
103
|
+
|
104
|
+
delete_statement = Arel::Nodes::DeleteStatement.new
|
105
|
+
delete_statement.relation = table
|
106
|
+
delete_statement.wheres = [table[:id].in(subquery)]
|
107
|
+
|
67
108
|
loop do
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
109
|
+
deleted_count = item_class
|
110
|
+
.connection
|
111
|
+
.execute(delete_statement.to_sql)
|
112
|
+
.cmd_tuples
|
113
|
+
|
114
|
+
logger.log_info("Deleted #{deleted_count} #{box_type} items for #{box_name} items")
|
115
|
+
break if deleted_count == 0
|
116
|
+
lock_timer.checkpoint!
|
117
|
+
sleep(SLEEP_TIME)
|
118
|
+
end
|
119
|
+
end
|
72
120
|
|
73
|
-
|
74
|
-
|
121
|
+
# Deletes stale items from MySQL database in batches
|
122
|
+
#
|
123
|
+
# This method efficiently deletes items older than the given waterline
|
124
|
+
# using MySQL's built-in LIMIT clause for DELETE statements.
|
125
|
+
#
|
126
|
+
# The main difference from the PostgreSQL method is that MySQL allows
|
127
|
+
# direct use of LIMIT in DELETE statements, simplifying the query.
|
128
|
+
# This approach doesn't require a subquery, making it more straightforward.
|
129
|
+
#
|
130
|
+
# Example SQL generated for deletion:
|
131
|
+
# DELETE FROM `items`
|
132
|
+
# WHERE `items`.`created_at` < '2023-05-01 00:00:00'
|
133
|
+
# LIMIT 1000
|
134
|
+
def mysql_delete_in_batches(waterline)
|
135
|
+
loop do
|
136
|
+
deleted_count = item_class
|
137
|
+
.where("created_at < ?", waterline)
|
138
|
+
.limit(BATCH_SIZE)
|
139
|
+
.delete_all
|
140
|
+
|
141
|
+
logger.log_info("Deleted #{deleted_count} #{box_type} items for #{box_name} items")
|
142
|
+
break if deleted_count == 0
|
143
|
+
lock_timer.checkpoint!
|
144
|
+
sleep(SLEEP_TIME)
|
75
145
|
end
|
146
|
+
end
|
76
147
|
|
77
|
-
|
148
|
+
def database_type
|
149
|
+
adapter_name = item_class.connection.adapter_name.downcase
|
150
|
+
case adapter_name
|
151
|
+
when "postgresql"
|
152
|
+
:postgresql
|
153
|
+
when "mysql2"
|
154
|
+
:mysql
|
155
|
+
else
|
156
|
+
:unknown
|
157
|
+
end
|
78
158
|
end
|
79
159
|
end
|
80
160
|
end
|
data/lib/sbmt/outbox/version.rb
CHANGED
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.10.
|
4
|
+
version: 6.10.3
|
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: 2024-10-
|
11
|
+
date: 2024-10-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: connection_pool
|
@@ -348,56 +348,42 @@ dependencies:
|
|
348
348
|
requirements:
|
349
349
|
- - ">="
|
350
350
|
- !ruby/object:Gem::Version
|
351
|
-
version: '
|
351
|
+
version: '2.5'
|
352
352
|
type: :development
|
353
353
|
prerelease: false
|
354
354
|
version_requirements: !ruby/object:Gem::Requirement
|
355
355
|
requirements:
|
356
356
|
- - ">="
|
357
357
|
- !ruby/object:Gem::Version
|
358
|
-
version: '
|
358
|
+
version: '2.5'
|
359
359
|
- !ruby/object:Gem::Dependency
|
360
360
|
name: rubocop-rspec
|
361
361
|
requirement: !ruby/object:Gem::Requirement
|
362
362
|
requirements:
|
363
363
|
- - ">="
|
364
364
|
- !ruby/object:Gem::Version
|
365
|
-
version: '
|
365
|
+
version: '2.11'
|
366
366
|
type: :development
|
367
367
|
prerelease: false
|
368
368
|
version_requirements: !ruby/object:Gem::Requirement
|
369
369
|
requirements:
|
370
370
|
- - ">="
|
371
371
|
- !ruby/object:Gem::Version
|
372
|
-
version: '
|
373
|
-
- !ruby/object:Gem::Dependency
|
374
|
-
name: rubocop-performance
|
375
|
-
requirement: !ruby/object:Gem::Requirement
|
376
|
-
requirements:
|
377
|
-
- - ">="
|
378
|
-
- !ruby/object:Gem::Version
|
379
|
-
version: '0'
|
380
|
-
type: :development
|
381
|
-
prerelease: false
|
382
|
-
version_requirements: !ruby/object:Gem::Requirement
|
383
|
-
requirements:
|
384
|
-
- - ">="
|
385
|
-
- !ruby/object:Gem::Version
|
386
|
-
version: '0'
|
372
|
+
version: '2.11'
|
387
373
|
- !ruby/object:Gem::Dependency
|
388
374
|
name: standard
|
389
375
|
requirement: !ruby/object:Gem::Requirement
|
390
376
|
requirements:
|
391
377
|
- - ">="
|
392
378
|
- !ruby/object:Gem::Version
|
393
|
-
version: '1.
|
379
|
+
version: '1.12'
|
394
380
|
type: :development
|
395
381
|
prerelease: false
|
396
382
|
version_requirements: !ruby/object:Gem::Requirement
|
397
383
|
requirements:
|
398
384
|
- - ">="
|
399
385
|
- !ruby/object:Gem::Version
|
400
|
-
version: '1.
|
386
|
+
version: '1.12'
|
401
387
|
- !ruby/object:Gem::Dependency
|
402
388
|
name: schked
|
403
389
|
requirement: !ruby/object:Gem::Requirement
|
@@ -640,7 +626,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
640
626
|
- !ruby/object:Gem::Version
|
641
627
|
version: '0'
|
642
628
|
requirements: []
|
643
|
-
rubygems_version: 3.
|
629
|
+
rubygems_version: 3.5.21
|
644
630
|
signing_key:
|
645
631
|
specification_version: 4
|
646
632
|
summary: Outbox service
|