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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3d126fdf9fae2bd957760dd1fdf1cac821e5103eb691fc2b293b3bda6170bb5c
4
- data.tar.gz: 977e7915aea7e1e389ad95c190e5ae749a868f869f1d28542ee264342f57b89e
3
+ metadata.gz: 2801cf9e3bb894d8c46915457a1b1cf2f77ca10e49e1947665eb077a8bb58378
4
+ data.tar.gz: 558b1db888887f7463c8cafc3399001341be364dea5e5ff15d88a1213d9ed420
5
5
  SHA512:
6
- metadata.gz: 407591bf52c6068c6133b1654a68ffacb4aae0c0d941f7bdab9536a682c70a0a3ca04017c68e61ac6475fbd75a0b7cb93c35b1ce94e6e54b69fb638020802225
7
- data.tar.gz: d5a69e5b56e07f4c90dcd5fea9f28f491c56f832acdd821b081ee5d3bb068af516b9ca114d464cda4f154edf4765b91c3d10c05f60b31c6612b5e72dca0c79ec
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(previous_delayed_jobs_shard_id: nil).find_each do |shard|
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 previous_delayed_jobs_shard and should
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.previous_delayed_jobs_shard_id && shard.delayed_jobs_shard.id == target_shard
52
- source_shards[shard.previous_delayed_jobs_shard_id] += [shard.id]
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 = { previous_delayed_jobs_shard_id: source_shard }
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(previous_delayed_jobs_shard_id: nil)
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.jobs_held = true
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.jobs_held = false
44
- if changed?
45
- save!
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
- # unlocked
54
+ # locked
49
55
  Rails.logger.debug("Waiting for caches to clear")
50
- sleep(65)
51
- end
52
- delayed_jobs_shard.activate(::Delayed::Backend::ActiveRecord::AbstractJob) do
53
- ::Delayed::Job.where(locked_by: ::Delayed::Backend::Base::ON_HOLD_LOCKED_BY, shard_id: id)
54
- .in_batches(of: 10_000)
55
- .update_all(
56
- locked_by: nil,
57
- locked_at: nil,
58
- attempts: 0,
59
- failed_at: nil
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
- def lock_jobs_for_hold
67
- ::Delayed::Job.where(locked_at: nil, shard_id: id).in_batches(of: 10_000).update_all(
68
- locked_by: ::Delayed::Backend::Base::ON_HOLD_LOCKED_BY,
69
- locked_at: ::Delayed::Job.db_time_now,
70
- attempts: ::Delayed::Backend::Base::ON_HOLD_COUNT
71
- )
72
- end
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SwitchmanInstJobs
4
- VERSION = "4.3.1"
4
+ VERSION = "4.3.3"
5
5
  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.1
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-01-20 00:00:00.000000000 Z
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/20260120092005_add_previous_jobs_shard.rb
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
@@ -1,7 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class AddPreviousJobsShard < ActiveRecord::Migration[7.1]
4
- def change
5
- add_reference :switchman_shards, :previous_delayed_jobs_shard, foreign_key: { to_table: :switchman_shards }, index: false, if_not_exists: true
6
- end
7
- end