switchman-inst-jobs 4.3.1 → 4.3.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/db/migrate/20260120092005_add_migrate_from_jobs_shard.rb +7 -0
- data/lib/switchman_inst_jobs/jobs_migrator.rb +6 -6
- data/lib/switchman_inst_jobs/switchman/shard.rb +83 -41
- data/lib/switchman_inst_jobs/version.rb +1 -1
- metadata +3 -3
- data/db/migrate/20260120092005_add_previous_jobs_shard.rb +0 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2801cf9e3bb894d8c46915457a1b1cf2f77ca10e49e1947665eb077a8bb58378
|
|
4
|
+
data.tar.gz: 558b1db888887f7463c8cafc3399001341be364dea5e5ff15d88a1213d9ed420
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b01ca10ff4988509cee9728241d954b4b9bbfc6e2c9971730235f9adbcf50694bcae0226362f68a9e5602591368cf24e866ea0fbf653b05091184f7406fef774
|
|
7
|
+
data.tar.gz: 0b15b1296d8b5bf887f7ca8bd745886757e57e76591829ea2028b4c7a7c803bd86bc219cca4df630b49e8d61807b088437f94c5eb40b0daa8aac4111ebedb4fd
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class AddMigrateFromJobsShard < ActiveRecord::Migration[7.1]
|
|
4
|
+
def change
|
|
5
|
+
add_reference :switchman_shards, :migrate_from_delayed_jobs_shard, foreign_key: { to_table: :switchman_shards }, index: false, if_not_exists: true
|
|
6
|
+
end
|
|
7
|
+
end
|
|
@@ -39,17 +39,17 @@ module SwitchmanInstJobs
|
|
|
39
39
|
source_shards = Hash.new([].freeze)
|
|
40
40
|
target_shards = Hash.new([].freeze)
|
|
41
41
|
# Also add any incomplete moves to the source shards to ensure we clean up appropriately
|
|
42
|
-
::Switchman::Shard.where.not(
|
|
42
|
+
::Switchman::Shard.where.not(migrate_from_delayed_jobs_shard_id: nil).find_each do |shard|
|
|
43
43
|
effective_map[shard.id] ||= shard.delayed_jobs_shard.id
|
|
44
44
|
end
|
|
45
45
|
effective_map.each do |(shard, target_shard)|
|
|
46
46
|
shard = ::Switchman::Shard.find(shard) unless shard.is_a?(::Switchman::Shard)
|
|
47
47
|
target_shard = target_shard.try(:id) || target_shard
|
|
48
48
|
# if a move was interrupted, the new shard is already set as the delayed_jobs_shard
|
|
49
|
-
# but we still have the old shard stored in
|
|
49
|
+
# but we still have the old shard stored in migrate_from_delayed_jobs_shard and should
|
|
50
50
|
# act as if we are moving from there in the first place
|
|
51
|
-
if shard.
|
|
52
|
-
source_shards[shard.
|
|
51
|
+
if shard.migrate_from_delayed_jobs_shard_id && shard.delayed_jobs_shard.id == target_shard
|
|
52
|
+
source_shards[shard.migrate_from_delayed_jobs_shard_id] += [shard.id]
|
|
53
53
|
else
|
|
54
54
|
source_shards[shard.delayed_jobs_shard.id] += [shard.id]
|
|
55
55
|
end
|
|
@@ -63,7 +63,7 @@ module SwitchmanInstJobs
|
|
|
63
63
|
::Switchman::Shard.transaction do
|
|
64
64
|
# Do the updates in batches and then just clear redis instead of clearing them one at a time
|
|
65
65
|
source_shards.each do |source_shard, shards|
|
|
66
|
-
updates = {
|
|
66
|
+
updates = { migrate_from_delayed_jobs_shard_id: source_shard }
|
|
67
67
|
::Switchman::Shard.where(id: shards).update_all(updates)
|
|
68
68
|
end
|
|
69
69
|
target_shards.each do |target_shard, shards|
|
|
@@ -86,7 +86,7 @@ module SwitchmanInstJobs
|
|
|
86
86
|
end
|
|
87
87
|
ensure_unblock_stranded_for(effective_map.map(&:first))
|
|
88
88
|
# rubocop:enable Style/CombinableLoops
|
|
89
|
-
::Switchman::Shard.where(id: effective_map.map(&:first)).update_all(
|
|
89
|
+
::Switchman::Shard.where(id: effective_map.map(&:first)).update_all(migrate_from_delayed_jobs_shard_id: nil)
|
|
90
90
|
end
|
|
91
91
|
|
|
92
92
|
# if :migrate_strands ran on any shards that fell into scenario 1, then
|
|
@@ -22,56 +22,82 @@ module SwitchmanInstJobs
|
|
|
22
22
|
# Adapted from hold/unhold methods in base delayed jobs base
|
|
23
23
|
# Wait is required to be able to safely move jobs
|
|
24
24
|
def hold_jobs!(wait: false)
|
|
25
|
-
self.
|
|
26
|
-
save! if changed?
|
|
27
|
-
delayed_jobs_shard.activate(::Delayed::Backend::ActiveRecord::AbstractJob) do
|
|
28
|
-
lock_jobs_for_hold
|
|
29
|
-
end
|
|
30
|
-
return unless wait
|
|
31
|
-
|
|
32
|
-
delayed_jobs_shard.activate(::Delayed::Backend::ActiveRecord::AbstractJob) do
|
|
33
|
-
while ::Delayed::Job.where(shard_id: id)
|
|
34
|
-
.where.not(locked_at: nil)
|
|
35
|
-
.where.not(locked_by: ::Delayed::Backend::Base::ON_HOLD_LOCKED_BY).exists?
|
|
36
|
-
sleep 10
|
|
37
|
-
lock_jobs_for_hold
|
|
38
|
-
end
|
|
39
|
-
end
|
|
25
|
+
::Switchman::Shard.where(id: self).hold_jobs!(wait:)
|
|
40
26
|
end
|
|
41
27
|
|
|
42
28
|
def unhold_jobs!
|
|
43
|
-
self.
|
|
44
|
-
|
|
45
|
-
|
|
29
|
+
::Switchman::Shard.where(id: self).unhold_jobs!
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
module ClassMethods
|
|
33
|
+
# Adapted from hold/unhold methods in base delayed jobs base
|
|
34
|
+
# Wait is required to be able to safely move jobs
|
|
35
|
+
def hold_jobs!(wait: false)
|
|
36
|
+
shards = all.to_a
|
|
37
|
+
wait_for_caches = false
|
|
38
|
+
shards.each do |shard|
|
|
39
|
+
shard.jobs_held = true
|
|
40
|
+
if shard.changed?
|
|
41
|
+
shard.save!
|
|
42
|
+
wait_for_caches = true if wait
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
shards_by_jobs_shard(shards).each do |jobs_shard, shard_ids|
|
|
46
|
+
jobs_shard.activate(::Delayed::Backend::ActiveRecord::AbstractJob) do
|
|
47
|
+
lock_jobs_for_hold(shard_ids)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
return unless wait
|
|
51
|
+
|
|
46
52
|
# Wait a little over the 60 second in-process shard cache clearing
|
|
47
53
|
# threshold to ensure that all new jobs are now being enqueued
|
|
48
|
-
#
|
|
54
|
+
# locked
|
|
49
55
|
Rails.logger.debug("Waiting for caches to clear")
|
|
50
|
-
sleep(65)
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
56
|
+
sleep(65) if wait && wait_for_caches
|
|
57
|
+
|
|
58
|
+
shards_by_jobs_shard(shards).each do |jobs_shard, shard_ids|
|
|
59
|
+
jobs_shard.activate(::Delayed::Backend::ActiveRecord::AbstractJob) do
|
|
60
|
+
while ::Delayed::Job.where(shard_id: shard_ids)
|
|
61
|
+
.where.not(locked_at: nil)
|
|
62
|
+
.where.not(locked_by: ::Delayed::Backend::Base::ON_HOLD_LOCKED_BY).exists?
|
|
63
|
+
sleep 10
|
|
64
|
+
lock_jobs_for_hold(shard_ids)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
61
68
|
end
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
private
|
|
65
69
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
70
|
+
def unhold_jobs!
|
|
71
|
+
shards = all.to_a
|
|
72
|
+
waited = false
|
|
73
|
+
shards.each do |shard|
|
|
74
|
+
shard.jobs_held = false
|
|
75
|
+
next unless shard.changed?
|
|
76
|
+
|
|
77
|
+
shard.save!
|
|
78
|
+
next if waited
|
|
79
|
+
|
|
80
|
+
# Wait a little over the 60 second in-process shard cache clearing
|
|
81
|
+
# threshold to ensure that all new jobs are now being enqueued
|
|
82
|
+
# unlocked
|
|
83
|
+
Rails.logger.debug("Waiting for caches to clear")
|
|
84
|
+
sleep(65)
|
|
85
|
+
waited = true
|
|
86
|
+
end
|
|
87
|
+
shards_by_jobs_shard(shards).each do |jobs_shard, shard_ids|
|
|
88
|
+
jobs_shard.activate(::Delayed::Backend::ActiveRecord::AbstractJob) do
|
|
89
|
+
::Delayed::Job.where(locked_by: ::Delayed::Backend::Base::ON_HOLD_LOCKED_BY, shard_id: shard_ids)
|
|
90
|
+
.in_batches(of: 10_000)
|
|
91
|
+
.update_all(
|
|
92
|
+
locked_by: nil,
|
|
93
|
+
locked_at: nil,
|
|
94
|
+
attempts: 0,
|
|
95
|
+
failed_at: nil
|
|
96
|
+
)
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
73
100
|
|
|
74
|
-
module ClassMethods
|
|
75
101
|
def clear_cache
|
|
76
102
|
super
|
|
77
103
|
remove_instance_variable(:@delayed_jobs_shards) if instance_variable_defined?(:@delayed_jobs_shards)
|
|
@@ -130,6 +156,22 @@ module SwitchmanInstJobs
|
|
|
130
156
|
|
|
131
157
|
::Switchman::Shard.merge(scope)
|
|
132
158
|
end
|
|
159
|
+
|
|
160
|
+
private
|
|
161
|
+
|
|
162
|
+
# Group the given shards by the shard their jobs live on, returning a
|
|
163
|
+
# hash of delayed_jobs_shard => [shard_id, ...]
|
|
164
|
+
def shards_by_jobs_shard(shards)
|
|
165
|
+
shards.group_by(&:delayed_jobs_shard).transform_values { |group| group.map(&:id) }
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def lock_jobs_for_hold(shard_ids)
|
|
169
|
+
::Delayed::Job.where(locked_at: nil, shard_id: shard_ids).in_batches(of: 10_000).update_all(
|
|
170
|
+
locked_by: ::Delayed::Backend::Base::ON_HOLD_LOCKED_BY,
|
|
171
|
+
locked_at: ::Delayed::Job.db_time_now,
|
|
172
|
+
attempts: ::Delayed::Backend::Base::ON_HOLD_COUNT
|
|
173
|
+
)
|
|
174
|
+
end
|
|
133
175
|
end
|
|
134
176
|
end
|
|
135
177
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: switchman-inst-jobs
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 4.3.
|
|
4
|
+
version: 4.3.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Bryan Petty
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-06-24 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: inst-jobs
|
|
@@ -136,7 +136,7 @@ files:
|
|
|
136
136
|
- db/migrate/20220203063200_remove_old_singleton_index.rb
|
|
137
137
|
- db/migrate/20220328152900_add_failed_jobs_indicies.rb
|
|
138
138
|
- db/migrate/20220519204546_add_requeued_job_id_to_failed_jobs.rb
|
|
139
|
-
- db/migrate/
|
|
139
|
+
- db/migrate/20260120092005_add_migrate_from_jobs_shard.rb
|
|
140
140
|
- lib/switchman-inst-jobs.rb
|
|
141
141
|
- lib/switchman_inst_jobs.rb
|
|
142
142
|
- lib/switchman_inst_jobs/active_record/connection_adapters/postgresql_adapter.rb
|