switchman-inst-jobs 4.0.4 → 4.0.7

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.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/db/migrate/20101216224513_create_delayed_jobs.rb +0 -4
  3. data/db/migrate/20110208031356_add_delayed_jobs_tag.rb +0 -4
  4. data/db/migrate/20110426161613_add_delayed_jobs_max_attempts.rb +0 -4
  5. data/db/migrate/20110516225834_add_delayed_jobs_strand.rb +0 -4
  6. data/db/migrate/20110531144916_cleanup_delayed_jobs_indexes.rb +1 -5
  7. data/db/migrate/20110610213249_optimize_delayed_jobs.rb +0 -9
  8. data/db/migrate/20110831210257_add_delayed_jobs_next_in_strand.rb +6 -10
  9. data/db/migrate/20120510004759_delayed_jobs_delete_trigger_lock_for_update.rb +0 -4
  10. data/db/migrate/20120531150712_drop_psql_jobs_pop_fn.rb +0 -4
  11. data/db/migrate/20120607164022_delayed_jobs_use_advisory_locks.rb +0 -4
  12. data/db/migrate/20120607181141_index_jobs_on_locked_by.rb +0 -4
  13. data/db/migrate/20120608191051_add_jobs_run_at_index.rb +0 -4
  14. data/db/migrate/20120927184213_change_delayed_jobs_handler_to_text.rb +0 -4
  15. data/db/migrate/20140505215131_add_failed_jobs_original_job_id.rb +0 -4
  16. data/db/migrate/20140505215510_copy_failed_jobs_original_id.rb +2 -6
  17. data/db/migrate/20140505223637_drop_failed_jobs_original_id.rb +0 -4
  18. data/db/migrate/20140512213941_add_source_to_jobs.rb +0 -4
  19. data/db/migrate/20150807133223_add_max_concurrent_to_jobs.rb +0 -4
  20. data/db/migrate/20151123210429_add_expires_at_to_jobs.rb +0 -4
  21. data/db/migrate/20151210162949_improve_max_concurrent.rb +0 -4
  22. data/db/migrate/20161206323555_add_back_default_string_limits_jobs.rb +4 -8
  23. data/db/migrate/20170308045400_add_shard_id_to_delayed_jobs.rb +0 -4
  24. data/db/migrate/20181217155351_speed_up_max_concurrent_triggers.rb +0 -4
  25. data/db/migrate/20190726154743_make_critical_columns_not_null.rb +0 -4
  26. data/db/migrate/20200330230722_add_id_to_get_delayed_jobs_index.rb +0 -4
  27. data/db/migrate/20200824222232_speed_up_max_concurrent_delete_trigger.rb +0 -4
  28. data/db/migrate/20200825011002_add_strand_order_override.rb +0 -4
  29. data/db/migrate/20210812210128_add_singleton_column.rb +6 -6
  30. data/db/migrate/20210917232626_add_delete_conflicting_singletons_before_unlock_trigger.rb +1 -1
  31. data/db/migrate/20220328152900_add_failed_jobs_indicies.rb +12 -0
  32. data/db/migrate/20220519204546_add_requeued_job_id_to_failed_jobs.rb +7 -0
  33. data/lib/switchman_inst_jobs/delayed/backend/active_record/abstract_job.rb +27 -0
  34. data/lib/switchman_inst_jobs/jobs_migrator.rb +30 -5
  35. data/lib/switchman_inst_jobs/version.rb +1 -1
  36. data/lib/switchman_inst_jobs.rb +4 -4
  37. metadata +28 -32
  38. data/lib/switchman_inst_jobs/active_record/connection_adapters/connection_pool.rb +0 -15
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ee1540b8c0c200ee917338953c9ea377dc0f32f354175e0e6953435861333c5f
4
- data.tar.gz: 4e3912c490226c6f73c39d5923199e8d9cd661c8caeb6cef2fd6701b0dc5c08d
3
+ metadata.gz: ae45b4d36d114de61b5363b41fc5f348be9fdf9afe9ecbdb3fdf0100516823b4
4
+ data.tar.gz: 0c59713f5158a5433fff01e20d95048407112c95a9314e94ad91a2062bd1affa
5
5
  SHA512:
6
- metadata.gz: 6ee661bcf6f5335a5c6d4d7651936de85aedc6b01221700353b97c5bde61dc9a6c351948daaea70689e401962c4249efe56d359e377636dafafecb8d09ee4a49
7
- data.tar.gz: 91b155c2f00a89298a7c9de0b1ec854119534e92ae6e7d89b3823adf666ba0fc9ca045c2a4e10e2e0a337c3eb3a8f1d775a6718ae9adde7d396ee787164e0596
6
+ metadata.gz: f45f7ef1557d133f39d6ea813e5c387bb4e675ba47b18f9fbeef1abaa34876fba81b805a50183b8f22d650c6ca891d8def35b17557f95e5820809ceb50e1a3d3
7
+ data.tar.gz: 7c6bffe4777abfd8bf9cbece96ba3a24aad5df73421511ff4c9b5b4ed6345b722033a49095dd021d8ed50db1456567fc1a83eae3b9e02c658d0be09563deef39
@@ -1,8 +1,4 @@
1
1
  class CreateDelayedJobs < ActiveRecord::Migration[4.2]
2
- def connection
3
- Delayed::Backend::ActiveRecord::AbstractJob.connection
4
- end
5
-
6
2
  def up
7
3
  unless connection.adapter_name == 'PostgreSQL'
8
4
  raise("#{connection.adapter_name} is not supported for delayed jobs queue")
@@ -1,8 +1,4 @@
1
1
  class AddDelayedJobsTag < ActiveRecord::Migration[4.2]
2
- def connection
3
- Delayed::Backend::ActiveRecord::AbstractJob.connection
4
- end
5
-
6
2
  def up
7
3
  add_column :delayed_jobs, :tag, :string
8
4
  add_index :delayed_jobs, [:tag]
@@ -1,8 +1,4 @@
1
1
  class AddDelayedJobsMaxAttempts < ActiveRecord::Migration[4.2]
2
- def connection
3
- Delayed::Backend::ActiveRecord::AbstractJob.connection
4
- end
5
-
6
2
  def up
7
3
  add_column :delayed_jobs, :max_attempts, :integer
8
4
  end
@@ -1,8 +1,4 @@
1
1
  class AddDelayedJobsStrand < ActiveRecord::Migration[4.2]
2
- def connection
3
- Delayed::Backend::ActiveRecord::AbstractJob.connection
4
- end
5
-
6
2
  def up
7
3
  add_column :delayed_jobs, :strand, :string
8
4
  add_index :delayed_jobs, :strand
@@ -1,14 +1,10 @@
1
1
  class CleanupDelayedJobsIndexes < ActiveRecord::Migration[4.2]
2
- def connection
3
- Delayed::Backend::ActiveRecord::AbstractJob.connection
4
- end
5
-
6
2
  def up
7
3
  case connection.adapter_name
8
4
  when 'PostgreSQL'
9
5
  # "nulls first" syntax is postgresql specific, and allows for more
10
6
  # efficient querying for the next job
11
- connection.execute("CREATE INDEX get_delayed_jobs_index ON #{::Delayed::Job.quoted_table_name} (priority, run_at, failed_at nulls first, locked_at nulls first, queue)")
7
+ connection.execute("CREATE INDEX get_delayed_jobs_index ON #{connection.quote_table_name(::Delayed::Job.table_name)} (priority, run_at, failed_at nulls first, locked_at nulls first, queue)")
12
8
  else
13
9
  add_index :delayed_jobs, %w[priority run_at locked_at failed_at queue], name: 'get_delayed_jobs_index'
14
10
  end
@@ -1,8 +1,4 @@
1
1
  class OptimizeDelayedJobs < ActiveRecord::Migration[4.2]
2
- def connection
3
- Delayed::Backend::ActiveRecord::AbstractJob.connection
4
- end
5
-
6
2
  def up
7
3
  create_table :failed_jobs do |t|
8
4
  t.integer 'priority', default: 0
@@ -27,11 +23,6 @@ class OptimizeDelayedJobs < ActiveRecord::Migration[4.2]
27
23
 
28
24
  add_index :delayed_jobs, %w[run_at queue locked_at strand priority], name: 'index_delayed_jobs_for_get_next'
29
25
  add_index :delayed_jobs, %w[strand id], name: 'index_delayed_jobs_on_strand'
30
-
31
- # move all failed jobs to the new failed table
32
- Delayed::Backend::ActiveRecord::Job.where.not(failed_at: nil).find_each do |job|
33
- job.fail! unless job.on_hold?
34
- end
35
26
  end
36
27
 
37
28
  def down
@@ -1,15 +1,11 @@
1
1
  class AddDelayedJobsNextInStrand < ActiveRecord::Migration[4.2]
2
- def connection
3
- Delayed::Backend::ActiveRecord::AbstractJob.connection
4
- end
5
-
6
2
  def up
7
3
  remove_index :delayed_jobs, name: 'index_delayed_jobs_for_get_next'
8
4
 
9
5
  add_column :delayed_jobs, :next_in_strand, :boolean, default: true, null: false
10
6
 
11
7
  # create the new index
12
- connection.execute("CREATE INDEX get_delayed_jobs_index ON #{::Delayed::Job.quoted_table_name} (priority, run_at, queue) WHERE locked_at IS NULL AND next_in_strand = 't'")
8
+ connection.execute("CREATE INDEX get_delayed_jobs_index ON #{connection.quote_table_name(::Delayed::Job.table_name)} (priority, run_at, queue) WHERE locked_at IS NULL AND next_in_strand = 't'")
13
9
 
14
10
  # create the insert trigger
15
11
  execute(<<-CODE)
@@ -23,7 +19,7 @@ class AddDelayedJobsNextInStrand < ActiveRecord::Migration[4.2]
23
19
  END;
24
20
  $$ LANGUAGE plpgsql SET search_path TO #{::Switchman::Shard.current.name};
25
21
  CODE
26
- execute("CREATE TRIGGER delayed_jobs_before_insert_row_tr BEFORE INSERT ON #{::Delayed::Job.quoted_table_name} FOR EACH ROW WHEN (NEW.strand IS NOT NULL) EXECUTE PROCEDURE #{connection.quote_table_name('delayed_jobs_before_insert_row_tr_fn')}()")
22
+ execute("CREATE TRIGGER delayed_jobs_before_insert_row_tr BEFORE INSERT ON #{connection.quote_table_name(::Delayed::Job.table_name)} FOR EACH ROW WHEN (NEW.strand IS NOT NULL) EXECUTE PROCEDURE #{connection.quote_table_name('delayed_jobs_before_insert_row_tr_fn')}()")
27
23
 
28
24
  # create the delete trigger
29
25
  execute(<<-CODE)
@@ -34,15 +30,15 @@ class AddDelayedJobsNextInStrand < ActiveRecord::Migration[4.2]
34
30
  END;
35
31
  $$ LANGUAGE plpgsql SET search_path TO #{::Switchman::Shard.current.name};
36
32
  CODE
37
- execute("CREATE TRIGGER delayed_jobs_after_delete_row_tr AFTER DELETE ON #{::Delayed::Job.quoted_table_name} FOR EACH ROW WHEN (OLD.strand IS NOT NULL AND OLD.next_in_strand = 't') EXECUTE PROCEDURE #{connection.quote_table_name('delayed_jobs_after_delete_row_tr_fn')} ()")
33
+ execute("CREATE TRIGGER delayed_jobs_after_delete_row_tr AFTER DELETE ON #{connection.quote_table_name(::Delayed::Job.table_name)} FOR EACH ROW WHEN (OLD.strand IS NOT NULL AND OLD.next_in_strand = 't') EXECUTE PROCEDURE #{connection.quote_table_name('delayed_jobs_after_delete_row_tr_fn')} ()")
38
34
 
39
- execute(%{UPDATE #{::Delayed::Job.quoted_table_name} SET next_in_strand = 'f' WHERE strand IS NOT NULL AND id <> (SELECT id FROM #{::Delayed::Job.quoted_table_name} j2 WHERE j2.strand = delayed_jobs.strand ORDER BY j2.strand, j2.id ASC LIMIT 1)})
35
+ execute(%{UPDATE #{connection.quote_table_name(::Delayed::Job.table_name)} SET next_in_strand = 'f' WHERE strand IS NOT NULL AND id <> (SELECT id FROM #{connection.quote_table_name(::Delayed::Job.table_name)} j2 WHERE j2.strand = delayed_jobs.strand ORDER BY j2.strand, j2.id ASC LIMIT 1)})
40
36
  end
41
37
 
42
38
  def down
43
- execute %(DROP TRIGGER delayed_jobs_before_insert_row_tr ON #{::Delayed::Job.quoted_table_name})
39
+ execute %(DROP TRIGGER delayed_jobs_before_insert_row_tr ON #{connection.quote_table_name(::Delayed::Job.table_name)})
44
40
  execute %{DROP FUNCTION #{connection.quote_table_name('delayed_jobs_before_insert_row_tr_fn')} ()}
45
- execute %(DROP TRIGGER delayed_jobs_after_delete_row_tr ON #{::Delayed::Job.quoted_table_name})
41
+ execute %(DROP TRIGGER delayed_jobs_after_delete_row_tr ON #{connection.quote_table_name(::Delayed::Job.table_name)})
46
42
  execute %{DROP FUNCTION #{connection.quote_table_name('delayed_jobs_after_delete_row_tr_fn')} ()}
47
43
 
48
44
  remove_column :delayed_jobs, :next_in_strand
@@ -1,8 +1,4 @@
1
1
  class DelayedJobsDeleteTriggerLockForUpdate < ActiveRecord::Migration[4.2]
2
- def connection
3
- Delayed::Backend::ActiveRecord::AbstractJob.connection
4
- end
5
-
6
2
  def up
7
3
  if connection.adapter_name == 'PostgreSQL'
8
4
  execute(<<-CODE)
@@ -1,8 +1,4 @@
1
1
  class DropPsqlJobsPopFn < ActiveRecord::Migration[4.2]
2
- def connection
3
- Delayed::Backend::ActiveRecord::AbstractJob.connection
4
- end
5
-
6
2
  def up
7
3
  if connection.adapter_name == 'PostgreSQL'
8
4
  connection.execute('DROP FUNCTION IF EXISTS pop_from_delayed_jobs(varchar, varchar, integer, integer, timestamp without time zone)')
@@ -1,8 +1,4 @@
1
1
  class DelayedJobsUseAdvisoryLocks < ActiveRecord::Migration[4.2]
2
- def connection
3
- Delayed::Backend::ActiveRecord::AbstractJob.connection
4
- end
5
-
6
2
  def up
7
3
  # use an advisory lock based on the name of the strand, instead of locking the whole table
8
4
  # note that we're using half of the md5, so collisions are possible, but we don't really
@@ -1,10 +1,6 @@
1
1
  class IndexJobsOnLockedBy < ActiveRecord::Migration[4.2]
2
2
  disable_ddl_transaction!
3
3
 
4
- def connection
5
- Delayed::Backend::ActiveRecord::AbstractJob.connection
6
- end
7
-
8
4
  def up
9
5
  add_index :delayed_jobs, :locked_by, algorithm: :concurrently, where: 'locked_by IS NOT NULL'
10
6
  end
@@ -1,10 +1,6 @@
1
1
  class AddJobsRunAtIndex < ActiveRecord::Migration[4.2]
2
2
  disable_ddl_transaction!
3
3
 
4
- def connection
5
- Delayed::Backend::ActiveRecord::AbstractJob.connection
6
- end
7
-
8
4
  def up
9
5
  add_index :delayed_jobs, %w[run_at tag], algorithm: :concurrently
10
6
  end
@@ -1,8 +1,4 @@
1
1
  class ChangeDelayedJobsHandlerToText < ActiveRecord::Migration[4.2]
2
- def connection
3
- Delayed::Backend::ActiveRecord::AbstractJob.connection
4
- end
5
-
6
2
  def up
7
3
  change_column :delayed_jobs, :handler, :text
8
4
  end
@@ -1,8 +1,4 @@
1
1
  class AddFailedJobsOriginalJobId < ActiveRecord::Migration[4.2]
2
- def connection
3
- Delayed::Backend::ActiveRecord::AbstractJob.connection
4
- end
5
-
6
2
  def up
7
3
  add_column :failed_jobs, :original_job_id, :integer, limit: 8
8
4
  end
@@ -1,11 +1,7 @@
1
1
  class CopyFailedJobsOriginalId < ActiveRecord::Migration[4.2]
2
- def connection
3
- Delayed::Backend::ActiveRecord::AbstractJob.connection
4
- end
5
-
6
2
  def up
7
- # this is a smaller, less frequently accessed table, so we just update all at once
8
- Delayed::Backend::ActiveRecord::Job::Failed.where(original_job_id: nil).update_all('original_job_id = original_id')
3
+ # Noop since we don't want to modify the shard using a different connection than the one we are using to build it and
4
+ # this migration is very old
9
5
  end
10
6
 
11
7
  def down; end
@@ -1,8 +1,4 @@
1
1
  class DropFailedJobsOriginalId < ActiveRecord::Migration[4.2]
2
- def connection
3
- Delayed::Backend::ActiveRecord::AbstractJob.connection
4
- end
5
-
6
2
  def up
7
3
  remove_column :failed_jobs, :original_id
8
4
  end
@@ -1,8 +1,4 @@
1
1
  class AddSourceToJobs < ActiveRecord::Migration[4.2]
2
- def connection
3
- Delayed::Backend::ActiveRecord::AbstractJob.connection
4
- end
5
-
6
2
  def up
7
3
  add_column :delayed_jobs, :source, :string
8
4
  add_column :failed_jobs, :source, :string
@@ -1,8 +1,4 @@
1
1
  class AddMaxConcurrentToJobs < ActiveRecord::Migration[4.2]
2
- def connection
3
- Delayed::Backend::ActiveRecord::AbstractJob.connection
4
- end
5
-
6
2
  def up
7
3
  add_column :delayed_jobs, :max_concurrent, :integer, default: 1, null: false
8
4
 
@@ -1,8 +1,4 @@
1
1
  class AddExpiresAtToJobs < ActiveRecord::Migration[4.2]
2
- def connection
3
- Delayed::Backend::ActiveRecord::AbstractJob.connection
4
- end
5
-
6
2
  def up
7
3
  add_column :delayed_jobs, :expires_at, :datetime
8
4
  add_column :failed_jobs, :expires_at, :datetime
@@ -1,8 +1,4 @@
1
1
  class ImproveMaxConcurrent < ActiveRecord::Migration[4.2]
2
- def connection
3
- Delayed::Backend::ActiveRecord::AbstractJob.connection
4
- end
5
-
6
2
  def up
7
3
  if connection.adapter_name == 'PostgreSQL'
8
4
  execute(<<-CODE)
@@ -1,8 +1,4 @@
1
1
  class AddBackDefaultStringLimitsJobs < ActiveRecord::Migration[4.2]
2
- def connection
3
- Delayed::Backend::ActiveRecord::AbstractJob.connection
4
- end
5
-
6
2
  def up
7
3
  drop_triggers
8
4
 
@@ -22,13 +18,13 @@ class AddBackDefaultStringLimitsJobs < ActiveRecord::Migration[4.2]
22
18
  end
23
19
 
24
20
  def drop_triggers
25
- execute %(DROP TRIGGER delayed_jobs_before_insert_row_tr ON #{::Delayed::Job.quoted_table_name})
26
- execute %(DROP TRIGGER delayed_jobs_after_delete_row_tr ON #{::Delayed::Job.quoted_table_name})
21
+ execute %(DROP TRIGGER delayed_jobs_before_insert_row_tr ON #{connection.quote_table_name(::Delayed::Job.table_name)})
22
+ execute %(DROP TRIGGER delayed_jobs_after_delete_row_tr ON #{connection.quote_table_name(::Delayed::Job.table_name)})
27
23
  end
28
24
 
29
25
  def readd_triggers
30
- execute("CREATE TRIGGER delayed_jobs_before_insert_row_tr BEFORE INSERT ON #{::Delayed::Job.quoted_table_name} FOR EACH ROW WHEN (NEW.strand IS NOT NULL) EXECUTE PROCEDURE #{connection.quote_table_name('delayed_jobs_before_insert_row_tr_fn')}()")
31
- execute("CREATE TRIGGER delayed_jobs_after_delete_row_tr AFTER DELETE ON #{::Delayed::Job.quoted_table_name} FOR EACH ROW WHEN (OLD.strand IS NOT NULL AND OLD.next_in_strand = 't') EXECUTE PROCEDURE #{connection.quote_table_name('delayed_jobs_after_delete_row_tr_fn')}()")
26
+ execute("CREATE TRIGGER delayed_jobs_before_insert_row_tr BEFORE INSERT ON #{connection.quote_table_name(::Delayed::Job.table_name)} FOR EACH ROW WHEN (NEW.strand IS NOT NULL) EXECUTE PROCEDURE #{connection.quote_table_name('delayed_jobs_before_insert_row_tr_fn')}()")
27
+ execute("CREATE TRIGGER delayed_jobs_after_delete_row_tr AFTER DELETE ON #{connection.quote_table_name(::Delayed::Job.table_name)} FOR EACH ROW WHEN (OLD.strand IS NOT NULL AND OLD.next_in_strand = 't') EXECUTE PROCEDURE #{connection.quote_table_name('delayed_jobs_after_delete_row_tr_fn')}()")
32
28
  end
33
29
 
34
30
  def add_string_limit_if_missing(table, column)
@@ -1,10 +1,6 @@
1
1
  class AddShardIdToDelayedJobs < ActiveRecord::Migration[4.2]
2
2
  disable_ddl_transaction!
3
3
 
4
- def connection
5
- Delayed::Backend::ActiveRecord::AbstractJob.connection
6
- end
7
-
8
4
  def up
9
5
  add_column :delayed_jobs, :shard_id, :integer, limit: 8
10
6
  add_index :delayed_jobs, :shard_id, algorithm: :concurrently
@@ -1,8 +1,4 @@
1
1
  class SpeedUpMaxConcurrentTriggers < ActiveRecord::Migration[4.2]
2
- def connection
3
- Delayed::Backend::ActiveRecord::AbstractJob.connection
4
- end
5
-
6
2
  def up
7
3
  if connection.adapter_name == 'PostgreSQL'
8
4
  # tl;dr sacrifice some responsiveness to max_concurrent changes for faster performance
@@ -1,8 +1,4 @@
1
1
  class MakeCriticalColumnsNotNull < ActiveRecord::Migration[4.2]
2
- def connection
3
- Delayed::Backend::ActiveRecord::AbstractJob.connection
4
- end
5
-
6
2
  def up
7
3
  change_column_null :delayed_jobs, :run_at, false
8
4
  change_column_null :delayed_jobs, :queue, false
@@ -1,10 +1,6 @@
1
1
  class AddIdToGetDelayedJobsIndex < ActiveRecord::Migration[4.2]
2
2
  disable_ddl_transaction!
3
3
 
4
- def connection
5
- Delayed::Backend::ActiveRecord::AbstractJob.connection
6
- end
7
-
8
4
  def up
9
5
  rename_index :delayed_jobs, 'get_delayed_jobs_index', 'get_delayed_jobs_index_old'
10
6
  add_index :delayed_jobs, %i[queue priority run_at id],
@@ -1,8 +1,4 @@
1
1
  class SpeedUpMaxConcurrentDeleteTrigger < ActiveRecord::Migration[4.2]
2
- def connection
3
- Delayed::Backend::ActiveRecord::AbstractJob.connection
4
- end
5
-
6
2
  def up
7
3
  if connection.adapter_name == 'PostgreSQL'
8
4
  # tl;dr sacrifice some responsiveness to max_concurrent changes for faster performance
@@ -1,10 +1,6 @@
1
1
  class AddStrandOrderOverride < ActiveRecord::Migration[4.2]
2
2
  disable_ddl_transaction!
3
3
 
4
- def connection
5
- Delayed::Backend::ActiveRecord::AbstractJob.connection
6
- end
7
-
8
4
  def up
9
5
  add_column :delayed_jobs, :strand_order_override, :integer, default: 0, null: false
10
6
  add_column :failed_jobs, :strand_order_override, :integer, default: 0, null: false
@@ -181,20 +181,20 @@ class AddSingletonColumn < ActiveRecord::Migration[5.2]
181
181
  reversible do |direction|
182
182
  direction.up do
183
183
  drop_triggers
184
- execute("CREATE TRIGGER delayed_jobs_before_insert_row_tr BEFORE INSERT ON #{::Delayed::Job.quoted_table_name} FOR EACH ROW WHEN (NEW.strand IS NOT NULL OR NEW.singleton IS NOT NULL) EXECUTE PROCEDURE #{connection.quote_table_name('delayed_jobs_before_insert_row_tr_fn')}()")
185
- execute("CREATE TRIGGER delayed_jobs_after_delete_row_tr AFTER DELETE ON #{::Delayed::Job.quoted_table_name} FOR EACH ROW WHEN ((OLD.strand IS NOT NULL OR OLD.singleton IS NOT NULL) AND OLD.next_in_strand=true) EXECUTE PROCEDURE #{connection.quote_table_name('delayed_jobs_after_delete_row_tr_fn')}()")
184
+ execute("CREATE TRIGGER delayed_jobs_before_insert_row_tr BEFORE INSERT ON #{connection.quote_table_name(::Delayed::Job.table_name)} FOR EACH ROW WHEN (NEW.strand IS NOT NULL OR NEW.singleton IS NOT NULL) EXECUTE PROCEDURE #{connection.quote_table_name('delayed_jobs_before_insert_row_tr_fn')}()")
185
+ execute("CREATE TRIGGER delayed_jobs_after_delete_row_tr AFTER DELETE ON #{connection.quote_table_name(::Delayed::Job.table_name)} FOR EACH ROW WHEN ((OLD.strand IS NOT NULL OR OLD.singleton IS NOT NULL) AND OLD.next_in_strand=true) EXECUTE PROCEDURE #{connection.quote_table_name('delayed_jobs_after_delete_row_tr_fn')}()")
186
186
  end
187
187
  direction.down do
188
188
  drop_triggers
189
- execute("CREATE TRIGGER delayed_jobs_before_insert_row_tr BEFORE INSERT ON #{::Delayed::Job.quoted_table_name} FOR EACH ROW WHEN (NEW.strand IS NOT NULL) EXECUTE PROCEDURE #{connection.quote_table_name('delayed_jobs_before_insert_row_tr_fn')}()")
190
- execute("CREATE TRIGGER delayed_jobs_after_delete_row_tr AFTER DELETE ON #{::Delayed::Job.quoted_table_name} FOR EACH ROW WHEN (OLD.strand IS NOT NULL AND OLD.next_in_strand = 't') EXECUTE PROCEDURE #{connection.quote_table_name('delayed_jobs_after_delete_row_tr_fn()')}")
189
+ execute("CREATE TRIGGER delayed_jobs_before_insert_row_tr BEFORE INSERT ON #{connection.quote_table_name(::Delayed::Job.table_name)} FOR EACH ROW WHEN (NEW.strand IS NOT NULL) EXECUTE PROCEDURE #{connection.quote_table_name('delayed_jobs_before_insert_row_tr_fn')}()")
190
+ execute("CREATE TRIGGER delayed_jobs_after_delete_row_tr AFTER DELETE ON #{connection.quote_table_name(::Delayed::Job.table_name)} FOR EACH ROW WHEN (OLD.strand IS NOT NULL AND OLD.next_in_strand = 't') EXECUTE PROCEDURE #{connection.quote_table_name('delayed_jobs_after_delete_row_tr_fn()')}")
191
191
  end
192
192
  end
193
193
  end
194
194
  end
195
195
 
196
196
  def drop_triggers
197
- execute("DROP TRIGGER delayed_jobs_before_insert_row_tr ON #{::Delayed::Job.quoted_table_name}")
198
- execute("DROP TRIGGER delayed_jobs_after_delete_row_tr ON #{::Delayed::Job.quoted_table_name}")
197
+ execute("DROP TRIGGER delayed_jobs_before_insert_row_tr ON #{connection.quote_table_name(::Delayed::Job.table_name)}")
198
+ execute("DROP TRIGGER delayed_jobs_after_delete_row_tr ON #{connection.quote_table_name(::Delayed::Job.table_name)}")
199
199
  end
200
200
  end
@@ -13,7 +13,7 @@ class AddDeleteConflictingSingletonsBeforeUnlockTrigger < ActiveRecord::Migratio
13
13
  $$ LANGUAGE plpgsql SET search_path TO #{::Switchman::Shard.current.name};
14
14
  SQL
15
15
  execute(<<~SQL)
16
- CREATE TRIGGER delayed_jobs_before_unlock_delete_conflicting_singletons_row_tr BEFORE UPDATE ON #{::Delayed::Job.quoted_table_name} FOR EACH ROW WHEN (
16
+ CREATE TRIGGER delayed_jobs_before_unlock_delete_conflicting_singletons_row_tr BEFORE UPDATE ON #{connection.quote_table_name(::Delayed::Job.table_name)} FOR EACH ROW WHEN (
17
17
  OLD.singleton IS NOT NULL AND
18
18
  OLD.singleton=NEW.singleton AND
19
19
  OLD.locked_by IS NOT NULL AND
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ class AddFailedJobsIndicies < ActiveRecord::Migration[5.2]
4
+ disable_ddl_transaction!
5
+
6
+ def change
7
+ add_index :failed_jobs, :failed_at, algorithm: :concurrently
8
+ add_index :failed_jobs, :strand, where: 'strand IS NOT NULL', algorithm: :concurrently
9
+ add_index :failed_jobs, :singleton, where: 'singleton IS NOT NULL', algorithm: :concurrently
10
+ add_index :failed_jobs, :tag, algorithm: :concurrently
11
+ end
12
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class AddRequeuedJobIdToFailedJobs < ActiveRecord::Migration[6.0]
4
+ def change
5
+ add_column :failed_jobs, :requeued_job_id, :integer, limit: 8
6
+ end
7
+ end
@@ -0,0 +1,27 @@
1
+ module SwitchmanInstJobs
2
+ module Delayed
3
+ module Backend
4
+ module ActiveRecord
5
+ module AbstractJob
6
+ module ClassMethods
7
+ def current_switchman_shard
8
+ connected_to_stack.reverse_each do |hash|
9
+ if hash[:switchman_shard] && hash[:klasses].include?(connection_class_for_self)
10
+ return hash[:switchman_shard]
11
+ end
12
+ end
13
+
14
+ ::ActiveRecord::Base.current_switchman_shard.delayed_jobs_shard
15
+ end
16
+ end
17
+
18
+ def self.prepended(base)
19
+ base.singleton_class.prepend(ClassMethods)
20
+
21
+ base.sharded_model
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -100,7 +100,7 @@ module SwitchmanInstJobs
100
100
  # those (= do nothing since it should already be false)
101
101
  # 4) no running job, jobs moved: set next_in_strand=true on the first of
102
102
  # those (= do nothing since it should already be true)
103
- handler = lambda { |scope, column, blocker_job_kwargs = {}|
103
+ handler = lambda { |scope, column, blocker_job_kwargs = {}, advisory_lock_cb = nil|
104
104
  shard_map = build_shard_map(scope, source_shard)
105
105
  shard_map.each do |(target_shard, source_shard_ids)|
106
106
  shard_scope = scope.where(shard_id: source_shard_ids)
@@ -111,6 +111,10 @@ module SwitchmanInstJobs
111
111
  target_shard.activate(::Delayed::Backend::ActiveRecord::AbstractJob) do
112
112
  values.each do |value|
113
113
  transaction_on([source_shard, target_shard]) do
114
+ source_shard.activate(::Delayed::Backend::ActiveRecord::AbstractJob) do
115
+ advisory_lock_cb&.call(value)
116
+ end
117
+
114
118
  value_scope = shard_scope.where(**{ column => value })
115
119
  # we want to copy all the jobs except the one that is still running.
116
120
  jobs_scope = value_scope.where(locked_by: nil)
@@ -123,7 +127,13 @@ module SwitchmanInstJobs
123
127
  # the lock ensures the blocker always gets unlocked
124
128
  first = value_scope.where.not(locked_by: nil).next_in_strand_order.lock.first
125
129
  if first
126
- create_blocker_job(queue: first.queue, **{ column => value }, **blocker_job_kwargs)
130
+ create_blocker_job(
131
+ queue: first.queue,
132
+ shard_id: first.shard_id,
133
+ **{ column => value },
134
+ **blocker_job_kwargs
135
+ )
136
+
127
137
  # the rest of 3) is taken care of here
128
138
  # make sure that all the jobs moved over are NOT next in strand
129
139
  ::Delayed::Job.where(next_in_strand: true, locked_by: nil, **{ column => value }).
@@ -151,9 +161,24 @@ module SwitchmanInstJobs
151
161
  singleton_scope = ::Delayed::Job.shard(source_shard).where('strand IS NULL AND singleton IS NOT NULL')
152
162
  all_scope = ::Delayed::Job.shard(source_shard).where('strand IS NOT NULL OR singleton IS NOT NULL')
153
163
 
154
- handler.call(strand_scope, :strand)
155
- handler.call(singleton_scope, :singleton,
156
- { locked_at: DateTime.now, locked_by: ::Delayed::Backend::Base::ON_HOLD_BLOCKER })
164
+ singleton_blocker_additional_kwargs = {
165
+ locked_at: DateTime.now,
166
+ locked_by: ::Delayed::Backend::Base::ON_HOLD_BLOCKER
167
+ }
168
+
169
+ quoted_function_name = ::Delayed::Job.connection.quote_table_name('half_md5_as_bigint')
170
+ strand_advisory_lock_fn = lambda do |value|
171
+ ::Delayed::Job.connection.execute("SELECT pg_advisory_xact_lock(#{quoted_function_name}('#{value}'))")
172
+ end
173
+
174
+ singleton_advisory_lock_fn = lambda do |value|
175
+ ::Delayed::Job.connection.execute(
176
+ "SELECT pg_advisory_xact_lock(#{quoted_function_name}('singleton:#{value}'))"
177
+ )
178
+ end
179
+
180
+ handler.call(strand_scope, :strand, {}, strand_advisory_lock_fn)
181
+ handler.call(singleton_scope, :singleton, singleton_blocker_additional_kwargs, singleton_advisory_lock_fn)
157
182
 
158
183
  shard_map = build_shard_map(all_scope, source_shard)
159
184
  shard_map.each do |(target_shard, source_shard_ids)|
@@ -1,3 +1,3 @@
1
1
  module SwitchmanInstJobs
2
- VERSION = '4.0.4'.freeze
2
+ VERSION = '4.0.7'.freeze
3
3
  end
@@ -5,9 +5,6 @@ module SwitchmanInstJobs
5
5
  cattr_accessor :delayed_jobs_shard_fallback
6
6
 
7
7
  def self.initialize_active_record
8
- ::ActiveRecord::ConnectionAdapters::ConnectionPool.prepend(
9
- ActiveRecord::ConnectionAdapters::ConnectionPool
10
- )
11
8
  ::ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.prepend(
12
9
  ActiveRecord::ConnectionAdapters::PostgreSQLAdapter
13
10
  )
@@ -17,6 +14,9 @@ module SwitchmanInstJobs
17
14
  ::Delayed::Backend::ActiveRecord::Job.prepend(
18
15
  Delayed::Backend::Base
19
16
  )
17
+ ::Delayed::Backend::ActiveRecord::AbstractJob.prepend(
18
+ Delayed::Backend::ActiveRecord::AbstractJob
19
+ )
20
20
  ::Delayed::Pool.prepend Delayed::Pool
21
21
  ::Delayed::Worker.prepend Delayed::Worker
22
22
  ::Delayed::Worker::HealthCheck.prepend Delayed::Worker::HealthCheck
@@ -35,10 +35,10 @@ module SwitchmanInstJobs
35
35
  end
36
36
  end
37
37
 
38
- require 'switchman_inst_jobs/active_record/connection_adapters/connection_pool'
39
38
  require 'switchman_inst_jobs/active_record/connection_adapters/postgresql_adapter'
40
39
  require 'switchman_inst_jobs/active_record/migration'
41
40
  require 'switchman_inst_jobs/delayed/settings'
41
+ require 'switchman_inst_jobs/delayed/backend/active_record/abstract_job'
42
42
  require 'switchman_inst_jobs/delayed/backend/base'
43
43
  require 'switchman_inst_jobs/delayed/message_sending'
44
44
  require 'switchman_inst_jobs/delayed/pool'
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.0.4
4
+ version: 4.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bryan Petty
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-02-04 00:00:00.000000000 Z
11
+ date: 2022-06-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: inst-jobs
@@ -53,7 +53,7 @@ dependencies:
53
53
  version: '6.1'
54
54
  - - "<"
55
55
  - !ruby/object:Gem::Version
56
- version: '6.2'
56
+ version: '7.1'
57
57
  type: :runtime
58
58
  prerelease: false
59
59
  version_requirements: !ruby/object:Gem::Requirement
@@ -63,27 +63,35 @@ dependencies:
63
63
  version: '6.1'
64
64
  - - "<"
65
65
  - !ruby/object:Gem::Version
66
- version: '6.2'
66
+ version: '7.1'
67
67
  - !ruby/object:Gem::Dependency
68
68
  name: switchman
69
69
  requirement: !ruby/object:Gem::Requirement
70
70
  requirements:
71
71
  - - "~>"
72
72
  - !ruby/object:Gem::Version
73
- version: '3.0'
74
- - - ">="
75
- - !ruby/object:Gem::Version
76
- version: 3.0.1
73
+ version: '3.1'
77
74
  type: :runtime
78
75
  prerelease: false
79
76
  version_requirements: !ruby/object:Gem::Requirement
80
77
  requirements:
81
78
  - - "~>"
82
79
  - !ruby/object:Gem::Version
83
- version: '3.0'
84
- - - ">="
80
+ version: '3.1'
81
+ - !ruby/object:Gem::Dependency
82
+ name: appraisal
83
+ requirement: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - "~>"
86
+ - !ruby/object:Gem::Version
87
+ version: 2.3.0
88
+ type: :development
89
+ prerelease: false
90
+ version_requirements: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - "~>"
85
93
  - !ruby/object:Gem::Version
86
- version: 3.0.1
94
+ version: 2.3.0
87
95
  - !ruby/object:Gem::Dependency
88
96
  name: bundler
89
97
  requirement: !ruby/object:Gem::Requirement
@@ -280,21 +288,7 @@ dependencies:
280
288
  - - "~>"
281
289
  - !ruby/object:Gem::Version
282
290
  version: '0.21'
283
- - !ruby/object:Gem::Dependency
284
- name: wwtd
285
- requirement: !ruby/object:Gem::Requirement
286
- requirements:
287
- - - "~>"
288
- - !ruby/object:Gem::Version
289
- version: '1.4'
290
- type: :development
291
- prerelease: false
292
- version_requirements: !ruby/object:Gem::Requirement
293
- requirements:
294
- - - "~>"
295
- - !ruby/object:Gem::Version
296
- version: '1.4'
297
- description:
291
+ description:
298
292
  email:
299
293
  - bpetty@instructure.com
300
294
  executables: []
@@ -344,11 +338,13 @@ files:
344
338
  - db/migrate/20220128084800_update_insert_trigger_for_singleton_unique_constraint_change.rb
345
339
  - db/migrate/20220128084900_update_delete_trigger_for_singleton_unique_constraint_change.rb
346
340
  - db/migrate/20220203063200_remove_old_singleton_index.rb
341
+ - db/migrate/20220328152900_add_failed_jobs_indicies.rb
342
+ - db/migrate/20220519204546_add_requeued_job_id_to_failed_jobs.rb
347
343
  - lib/switchman-inst-jobs.rb
348
344
  - lib/switchman_inst_jobs.rb
349
- - lib/switchman_inst_jobs/active_record/connection_adapters/connection_pool.rb
350
345
  - lib/switchman_inst_jobs/active_record/connection_adapters/postgresql_adapter.rb
351
346
  - lib/switchman_inst_jobs/active_record/migration.rb
347
+ - lib/switchman_inst_jobs/delayed/backend/active_record/abstract_job.rb
352
348
  - lib/switchman_inst_jobs/delayed/backend/base.rb
353
349
  - lib/switchman_inst_jobs/delayed/message_sending.rb
354
350
  - lib/switchman_inst_jobs/delayed/pool.rb
@@ -371,7 +367,7 @@ licenses:
371
367
  metadata:
372
368
  allowed_push_host: https://rubygems.org
373
369
  rubygems_mfa_required: 'true'
374
- post_install_message:
370
+ post_install_message:
375
371
  rdoc_options: []
376
372
  require_paths:
377
373
  - lib
@@ -379,15 +375,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
379
375
  requirements:
380
376
  - - ">="
381
377
  - !ruby/object:Gem::Version
382
- version: '2.6'
378
+ version: '2.7'
383
379
  required_rubygems_version: !ruby/object:Gem::Requirement
384
380
  requirements:
385
381
  - - ">="
386
382
  - !ruby/object:Gem::Version
387
383
  version: '0'
388
384
  requirements: []
389
- rubygems_version: 3.1.4
390
- signing_key:
385
+ rubygems_version: 3.1.6
386
+ signing_key:
391
387
  specification_version: 4
392
388
  summary: Switchman and Instructure Jobs compatibility gem.
393
389
  test_files: []
@@ -1,15 +0,0 @@
1
- module SwitchmanInstJobs
2
- module ActiveRecord
3
- module ConnectionAdapters
4
- module ConnectionPool
5
- def shard
6
- if connection_klass == ::Delayed::Backend::ActiveRecord::AbstractJob
7
- return shard_stack.last || ::Switchman::Shard.current(::ActiveRecord::Base).delayed_jobs_shard
8
- end
9
-
10
- super
11
- end
12
- end
13
- end
14
- end
15
- end