sbmt-outbox 6.10.1 → 6.10.3
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:
|
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
|
@@ -74,7 +74,7 @@ module Sbmt
|
|
74
74
|
def partition_strategy
|
75
75
|
return @partition_strategy if defined?(@partition_strategy)
|
76
76
|
|
77
|
-
str_name = options.fetch(:partition_strategy, DEFAULT_PARTITION_STRATEGY)
|
77
|
+
str_name = options.fetch(:partition_strategy, DEFAULT_PARTITION_STRATEGY).to_s
|
78
78
|
@partition_strategy = "Sbmt::Outbox::PartitionStrategies::#{str_name.camelize}Partitioning".constantize
|
79
79
|
end
|
80
80
|
|
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-
|
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
|