solid_queue 0.2.0 → 0.2.1

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: 72d9dc2e30127c7b1fe101648d4d18b04af2d33491c729816e25dcf488246b54
4
- data.tar.gz: e39dcad251d4124355adcedfa9cb1ee88eea12043eb8505568332d9fcacee428
3
+ metadata.gz: 0eb31439e2768af5f5d3fb9289ac51056570c762ad140bc54aba81ee770d5a12
4
+ data.tar.gz: 4d3e4c2608b0a3ed2de82c7712c8a524e8745bc4e2ddf6907de8b3723560ab04
5
5
  SHA512:
6
- metadata.gz: 967732a5e679269543869ca64aa410bfc43c935ad3fb6856de0860bbe5cee58716e389b5935e48a91c6c658a84fa79aff9f5eae93ba3931344d31aff0d45c8fc
7
- data.tar.gz: 523af9f1b26a137d99ade0805bdc955cb81584971308928d5e16e83d3c46861947deaaa95ff96775d7eceb913f3d8995eca14707cda4533f7c3ee39f20afb650
6
+ metadata.gz: 0f4271aaf7b55b86d81f97bf19bbfa2b76de1ff994a6b71bb097b89ab9585212f28c0fdbd4fbb86b74c18b49cf229e7913eaa724784b3a62f000d60c2ade3263
7
+ data.tar.gz: a84d91b13db4a3ec96d1afa5fb5f39abc9ea0bf4bc216c14e20f4bf7e1bf2ff414e08f78166377950351b8170cbd734aa69322feb9076a67a3f9939ebacf6573
data/MIT-LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2023 37signals
1
+ Copyright (c) 37signals, LLC
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -31,7 +31,7 @@ $ bin/rails generate solid_queue:install
31
31
 
32
32
  This will set `solid_queue` as the Active Job's adapter in production, and will copy the required migration over to your app.
33
33
 
34
- Alternatively, you can add the only the migration to your app:
34
+ Alternatively, you can add only the migration to your app:
35
35
  ```bash
36
36
  $ bin/rails solid_queue:install:migrations
37
37
  ```
@@ -23,6 +23,14 @@ class SolidQueue::ClaimedExecution < SolidQueue::Execution
23
23
  def release_all
24
24
  includes(:job).each(&:release)
25
25
  end
26
+
27
+ def discard_all_in_batches(*)
28
+ raise UndiscardableError, "Can't discard jobs in progress"
29
+ end
30
+
31
+ def discard_all_from_jobs(*)
32
+ raise UndiscardableError, "Can't discard jobs in progress"
33
+ end
26
34
  end
27
35
 
28
36
  def perform
@@ -39,11 +47,15 @@ class SolidQueue::ClaimedExecution < SolidQueue::Execution
39
47
 
40
48
  def release
41
49
  transaction do
42
- job.prepare_for_execution
50
+ job.dispatch_bypassing_concurrency_limits
43
51
  destroy!
44
52
  end
45
53
  end
46
54
 
55
+ def discard
56
+ raise UndiscardableError, "Can't discard a job in progress"
57
+ end
58
+
47
59
  private
48
60
  def execute
49
61
  ActiveJob::Base.execute(job.arguments)
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SolidQueue
4
+ class Execution
5
+ module Dispatching
6
+ extend ActiveSupport::Concern
7
+
8
+ class_methods do
9
+ def dispatch_jobs(job_ids)
10
+ jobs = Job.where(id: job_ids)
11
+
12
+ Job.dispatch_all(jobs).map(&:id).tap do |dispatched_job_ids|
13
+ where(job_id: dispatched_job_ids).delete_all
14
+ SolidQueue.logger.info("[SolidQueue] Dispatched #{dispatched_job_ids.size} jobs")
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -6,23 +6,23 @@ module SolidQueue
6
6
  extend ActiveSupport::Concern
7
7
 
8
8
  included do
9
- class_attribute :assumible_attributes_from_job, instance_accessor: false, default: %i[ queue_name priority ]
9
+ class_attribute :assumable_attributes_from_job, instance_accessor: false, default: %i[ queue_name priority ]
10
10
  end
11
11
 
12
12
  class_methods do
13
13
  def assumes_attributes_from_job(*attribute_names)
14
- self.assumible_attributes_from_job |= attribute_names
14
+ self.assumable_attributes_from_job |= attribute_names
15
15
  before_create -> { assume_attributes_from_job }
16
16
  end
17
17
 
18
18
  def attributes_from_job(job)
19
- job.attributes.symbolize_keys.slice(*assumible_attributes_from_job)
19
+ job.attributes.symbolize_keys.slice(*assumable_attributes_from_job)
20
20
  end
21
21
  end
22
22
 
23
23
  private
24
24
  def assume_attributes_from_job
25
- self.class.assumible_attributes_from_job.each do |attribute|
25
+ self.class.assumable_attributes_from_job.each do |attribute|
26
26
  send("#{attribute}=", job.send(attribute))
27
27
  end
28
28
  end
@@ -2,6 +2,8 @@
2
2
 
3
3
  module SolidQueue
4
4
  class Execution < Record
5
+ class UndiscardableError < StandardError; end
6
+
5
7
  include JobAttributes
6
8
 
7
9
  self.abstract_class = true
@@ -10,8 +12,6 @@ module SolidQueue
10
12
 
11
13
  belongs_to :job
12
14
 
13
- alias_method :discard, :destroy
14
-
15
15
  class << self
16
16
  def create_all_from_jobs(jobs)
17
17
  insert_all execution_data_from_jobs(jobs)
@@ -22,6 +22,48 @@ module SolidQueue
22
22
  attributes_from_job(job).merge(job_id: job.id)
23
23
  end
24
24
  end
25
+
26
+ def discard_all_in_batches(batch_size: 500)
27
+ pending = count
28
+ discarded = 0
29
+
30
+ loop do
31
+ transaction do
32
+ job_ids = limit(batch_size).order(:job_id).lock.pluck(:job_id)
33
+
34
+ discard_jobs job_ids
35
+ discarded = where(job_id: job_ids).delete_all
36
+ pending -= discarded
37
+ end
38
+
39
+ break if pending <= 0 || discarded == 0
40
+ end
41
+ end
42
+
43
+ def discard_all_from_jobs(jobs)
44
+ transaction do
45
+ job_ids = lock_all_from_jobs(jobs)
46
+
47
+ discard_jobs job_ids
48
+ where(job_id: job_ids).delete_all
49
+ end
50
+ end
51
+
52
+ private
53
+ def lock_all_from_jobs(jobs)
54
+ where(job_id: jobs.map(&:id)).order(:job_id).lock.pluck(:job_id)
55
+ end
56
+
57
+ def discard_jobs(job_ids)
58
+ Job.where(id: job_ids).delete_all
59
+ end
60
+ end
61
+
62
+ def discard
63
+ with_lock do
64
+ job.destroy
65
+ destroy
66
+ end
25
67
  end
26
68
  end
27
69
  end
@@ -1,27 +1,37 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class SolidQueue::FailedExecution < SolidQueue::Execution
4
- serialize :error, coder: JSON
3
+ module SolidQueue
4
+ class FailedExecution < Execution
5
+ include Dispatching
5
6
 
6
- before_create :expand_error_details_from_exception
7
+ serialize :error, coder: JSON
7
8
 
8
- attr_accessor :exception
9
+ before_create :expand_error_details_from_exception
9
10
 
10
- def retry
11
- transaction do
12
- job.prepare_for_execution
13
- destroy!
11
+ attr_accessor :exception
12
+
13
+ def self.retry_all(jobs)
14
+ transaction do
15
+ dispatch_jobs lock_all_from_jobs(jobs)
16
+ end
17
+ end
18
+
19
+ def retry
20
+ with_lock do
21
+ job.prepare_for_execution
22
+ destroy!
23
+ end
14
24
  end
15
- end
16
25
 
17
- %i[ exception_class message backtrace ].each do |attribute|
18
- define_method(attribute) { error.with_indifferent_access[attribute] }
19
- end
26
+ %i[ exception_class message backtrace ].each do |attribute|
27
+ define_method(attribute) { error.with_indifferent_access[attribute] }
28
+ end
20
29
 
21
- private
22
- def expand_error_details_from_exception
23
- if exception
24
- self.error = { exception_class: exception.class.name, message: exception.message, backtrace: exception.backtrace }
30
+ private
31
+ def expand_error_details_from_exception
32
+ if exception
33
+ self.error = { exception_class: exception.class.name, message: exception.message, backtrace: exception.backtrace }
34
+ end
25
35
  end
26
36
  end
27
37
  end
@@ -11,7 +11,10 @@ module SolidQueue
11
11
 
12
12
  class_methods do
13
13
  def clear_finished_in_batches(batch_size: 500, finished_before: SolidQueue.clear_finished_jobs_after.ago)
14
- clearable(finished_before: finished_before).in_batches(of: batch_size).delete_all
14
+ loop do
15
+ records_deleted = clearable(finished_before: finished_before).limit(batch_size).delete_all
16
+ break if records_deleted == 0
17
+ end
15
18
  end
16
19
  end
17
20
  end
@@ -6,9 +6,17 @@ module SolidQueue
6
6
  extend ActiveSupport::Concern
7
7
 
8
8
  included do
9
- has_one :blocked_execution, dependent: :destroy
9
+ has_one :blocked_execution
10
10
 
11
11
  delegate :concurrency_limit, :concurrency_duration, to: :job_class
12
+
13
+ before_destroy :unblock_next_blocked_job, if: -> { concurrency_limited? && ready? }
14
+ end
15
+
16
+ class_methods do
17
+ def release_all_concurrency_locks(jobs)
18
+ Semaphore.signal_all(jobs.select(&:concurrency_limited?))
19
+ end
12
20
  end
13
21
 
14
22
  def unblock_next_blocked_job
@@ -21,6 +29,10 @@ module SolidQueue
21
29
  concurrency_key.present?
22
30
  end
23
31
 
32
+ def blocked?
33
+ blocked_execution.present?
34
+ end
35
+
24
36
  private
25
37
  def acquire_concurrency_lock
26
38
  return true unless concurrency_limited?
@@ -45,6 +57,10 @@ module SolidQueue
45
57
  def job_class
46
58
  @job_class ||= class_name.safe_constantize
47
59
  end
60
+
61
+ def execution
62
+ super || blocked_execution
63
+ end
48
64
  end
49
65
  end
50
66
  end
@@ -8,9 +8,9 @@ module SolidQueue
8
8
  included do
9
9
  include Clearable, ConcurrencyControls, Schedulable
10
10
 
11
- has_one :ready_execution, dependent: :destroy
12
- has_one :claimed_execution, dependent: :destroy
13
- has_one :failed_execution, dependent: :destroy
11
+ has_one :ready_execution
12
+ has_one :claimed_execution
13
+ has_one :failed_execution
14
14
 
15
15
  after_create :prepare_for_execution
16
16
 
@@ -73,6 +73,10 @@ module SolidQueue
73
73
  end
74
74
  end
75
75
 
76
+ def dispatch_bypassing_concurrency_limits
77
+ ready
78
+ end
79
+
76
80
  def finished!
77
81
  if preserve_finished_jobs?
78
82
  touch(:finished_at)
@@ -85,18 +89,22 @@ module SolidQueue
85
89
  finished_at.present?
86
90
  end
87
91
 
88
- def due?
89
- scheduled_at.nil? || scheduled_at <= Time.current
90
- end
91
-
92
- def discard
93
- destroy unless claimed?
92
+ def status
93
+ if finished?
94
+ :finished
95
+ elsif execution.present?
96
+ execution.model_name.element.sub("_execution", "").to_sym
97
+ end
94
98
  end
95
99
 
96
100
  def retry
97
101
  failed_execution&.retry
98
102
  end
99
103
 
104
+ def discard
105
+ execution&.discard
106
+ end
107
+
100
108
  def failed_with(exception)
101
109
  FailedExecution.create_or_find_by!(job_id: id, exception: exception)
102
110
  end
@@ -106,6 +114,9 @@ module SolidQueue
106
114
  ReadyExecution.create_or_find_by!(job_id: id)
107
115
  end
108
116
 
117
+ def execution
118
+ %w[ ready claimed failed ].reduce(nil) { |acc, status| acc || public_send("#{status}_execution") }
119
+ end
109
120
 
110
121
  def preserve_finished_jobs?
111
122
  SolidQueue.preserve_finished_jobs
@@ -6,7 +6,7 @@ module SolidQueue
6
6
  extend ActiveSupport::Concern
7
7
 
8
8
  included do
9
- has_one :scheduled_execution, dependent: :destroy
9
+ has_one :scheduled_execution
10
10
 
11
11
  scope :scheduled, -> { where.not(finished_at: nil) }
12
12
  end
@@ -31,10 +31,18 @@ module SolidQueue
31
31
  scheduled_at.nil? || scheduled_at <= Time.current
32
32
  end
33
33
 
34
+ def scheduled?
35
+ scheduled_execution.present?
36
+ end
37
+
34
38
  private
35
39
  def schedule
36
40
  ScheduledExecution.create_or_find_by!(job_id: id)
37
41
  end
42
+
43
+ def execution
44
+ super || scheduled_execution
45
+ end
38
46
  end
39
47
  end
40
48
  end
@@ -15,9 +15,12 @@ module SolidQueue
15
15
  prepare_all_for_execution(jobs).tap do |enqueued_jobs|
16
16
  enqueued_jobs.each do |enqueued_job|
17
17
  active_jobs_by_job_id[enqueued_job.active_job_id].provider_job_id = enqueued_job.id
18
+ active_jobs_by_job_id[enqueued_job.active_job_id].successfully_enqueued = true
18
19
  end
19
20
  end
20
21
  end
22
+
23
+ active_jobs.count(&:successfully_enqueued?)
21
24
  end
22
25
 
23
26
  def enqueue(active_job, scheduled_at: Time.current)
@@ -33,7 +33,7 @@ module SolidQueue
33
33
  end
34
34
 
35
35
  def clear
36
- Job.where(queue_name: name).each(&:discard)
36
+ ReadyExecution.queued_as(name).discard_all_in_batches
37
37
  end
38
38
 
39
39
  def size
@@ -15,6 +15,10 @@ module SolidQueue
15
15
  end
16
16
  end
17
17
 
18
+ def aggregated_count_across(queue_list)
19
+ QueueSelector.new(queue_list, self).scoped_relations.map(&:count).sum
20
+ end
21
+
18
22
  private
19
23
  def select_and_lock(queue_relation, process_id, limit)
20
24
  return [] if limit <= 0
@@ -36,6 +40,12 @@ module SolidQueue
36
40
  where(job_id: claimed.pluck(:job_id)).delete_all
37
41
  end
38
42
  end
43
+
44
+
45
+ def discard_jobs(job_ids)
46
+ Job.release_all_concurrency_locks Job.where(id: job_ids)
47
+ super
48
+ end
39
49
  end
40
50
  end
41
51
  end
@@ -2,6 +2,8 @@
2
2
 
3
3
  module SolidQueue
4
4
  class ScheduledExecution < Execution
5
+ include Dispatching
6
+
5
7
  scope :due, -> { where(scheduled_at: ..Time.current) }
6
8
  scope :ordered, -> { order(scheduled_at: :asc, priority: :asc) }
7
9
  scope :next_batch, ->(batch_size) { due.ordered.limit(batch_size) }
@@ -14,20 +16,10 @@ module SolidQueue
14
16
  job_ids = next_batch(batch_size).non_blocking_lock.pluck(:job_id)
15
17
  if job_ids.empty? then []
16
18
  else
17
- dispatch_batch(job_ids)
19
+ dispatch_jobs(job_ids)
18
20
  end
19
21
  end
20
22
  end
21
-
22
- private
23
- def dispatch_batch(job_ids)
24
- jobs = Job.where(id: job_ids)
25
-
26
- Job.dispatch_all(jobs).map(&:id).tap do |dispatched_job_ids|
27
- where(job_id: dispatched_job_ids).delete_all
28
- SolidQueue.logger.info("[SolidQueue] Dispatched scheduled batch with #{dispatched_job_ids.size} jobs")
29
- end
30
- end
31
23
  end
32
24
  end
33
25
  end
@@ -1,65 +1,94 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class SolidQueue::Semaphore < SolidQueue::Record
4
- scope :available, -> { where("value > 0") }
5
- scope :expired, -> { where(expires_at: ...Time.current) }
3
+ module SolidQueue
4
+ class Semaphore < Record
5
+ scope :available, -> { where("value > 0") }
6
+ scope :expired, -> { where(expires_at: ...Time.current) }
6
7
 
7
- class << self
8
- def wait(job)
9
- Proxy.new(job, self).wait
10
- end
11
-
12
- def signal(job)
13
- Proxy.new(job, self).signal
14
- end
15
- end
16
-
17
- class Proxy
18
- def initialize(job, proxied_class)
19
- @job = job
20
- @proxied_class = proxied_class
21
- end
8
+ class << self
9
+ def wait(job)
10
+ Proxy.new(job).wait
11
+ end
22
12
 
23
- def wait
24
- if semaphore = proxied_class.find_by(key: key)
25
- semaphore.value > 0 && attempt_decrement
26
- else
27
- attempt_creation
13
+ def signal(job)
14
+ Proxy.new(job).signal
28
15
  end
29
- end
30
16
 
31
- def signal
32
- attempt_increment
17
+ def signal_all(jobs)
18
+ Proxy.signal_all(jobs)
19
+ end
33
20
  end
34
21
 
35
- private
36
- attr_reader :job, :proxied_class
37
-
38
- def attempt_creation
39
- proxied_class.create!(key: key, value: limit - 1, expires_at: expires_at)
40
- true
41
- rescue ActiveRecord::RecordNotUnique
42
- attempt_decrement
22
+ class Proxy
23
+ def self.signal_all(jobs)
24
+ Semaphore.where(key: jobs.map(&:concurrency_key)).update_all("value = value + 1")
43
25
  end
44
26
 
45
- def attempt_decrement
46
- proxied_class.available.where(key: key).update_all([ "value = value - 1, expires_at = ?", expires_at ]) > 0
27
+ def initialize(job)
28
+ @job = job
29
+ @retries = 0
47
30
  end
48
31
 
49
- def attempt_increment
50
- proxied_class.where(key: key, value: ...limit).update_all([ "value = value + 1, expires_at = ?", expires_at ]) > 0
32
+ def wait
33
+ if semaphore = Semaphore.find_by(key: key)
34
+ semaphore.value > 0 && attempt_decrement
35
+ else
36
+ attempt_creation
37
+ end
51
38
  end
52
39
 
53
- def key
54
- job.concurrency_key
40
+ def signal
41
+ attempt_increment
55
42
  end
56
43
 
57
- def expires_at
58
- job.concurrency_duration.from_now
59
- end
44
+ private
45
+ attr_accessor :job, :retries
60
46
 
61
- def limit
62
- job.concurrency_limit
63
- end
47
+ def attempt_creation
48
+ Semaphore.create!(key: key, value: limit - 1, expires_at: expires_at)
49
+ true
50
+ rescue ActiveRecord::RecordNotUnique
51
+ attempt_decrement
52
+ end
53
+
54
+ def attempt_decrement
55
+ Semaphore.available.where(key: key).update_all([ "value = value - 1, expires_at = ?", expires_at ]) > 0
56
+ rescue ActiveRecord::Deadlocked
57
+ if retriable? then attempt_retry
58
+ else
59
+ raise
60
+ end
61
+ end
62
+
63
+ def attempt_increment
64
+ Semaphore.where(key: key, value: ...limit).update_all([ "value = value + 1, expires_at = ?", expires_at ]) > 0
65
+ end
66
+
67
+ def attempt_retry
68
+ self.retries += 1
69
+
70
+ if semaphore = Semaphore.find_by(key: key)
71
+ semaphore.value > 0 && attempt_decrement
72
+ end
73
+ end
74
+
75
+ MAX_RETRIES = 1
76
+
77
+ def retriable?
78
+ retries < MAX_RETRIES
79
+ end
80
+
81
+ def key
82
+ job.concurrency_key
83
+ end
84
+
85
+ def expires_at
86
+ job.concurrency_duration.from_now
87
+ end
88
+
89
+ def limit
90
+ job.concurrency_limit
91
+ end
92
+ end
64
93
  end
65
94
  end
@@ -0,0 +1,5 @@
1
+ class AddMissingIndexToBlockedExecutions < ActiveRecord::Migration[7.1]
2
+ def change
3
+ add_index :solid_queue_blocked_executions, [ :concurrency_key, :priority, :job_id ], name: "index_solid_queue_blocked_executions_for_release"
4
+ end
5
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveJob
4
+ module Uniqueness
5
+ extend ActiveSupport::Concern
6
+
7
+ DEFAULT_UNIQUENESS_GROUP = ->(*) { self.class.name }
8
+
9
+ included do
10
+ class_attribute :uniqueness_key, instance_accessor: false
11
+ class_attribute :uniqueness_group, default: DEFAULT_UNIQUENESS_GROUP, instance_accessor: false
12
+
13
+ class_attribute :uniqueness_duration
14
+ end
15
+
16
+ class_methods do
17
+ def enqueued_uniquely_by(key:, group: DEFAULT_UNIQUENESS_GROUP, duration: SolidQueue.default_uniqueness_period)
18
+ self.uniqueness_key = key
19
+ self.uniqueness_group = group
20
+ self.uniqueness_duration = duration
21
+ end
22
+ end
23
+
24
+ def uniqueness_key
25
+ if self.class.uniqueness_key
26
+ param = compute_concurrency_parameter(self.class.concurrency_key)
27
+
28
+ case param
29
+ when ActiveRecord::Base
30
+ [ concurrency_group, param.class.name, param.id ]
31
+ else
32
+ [ concurrency_group, param ]
33
+ end.compact.join("/")
34
+ end
35
+ end
36
+
37
+ def enqueued_uniquely?
38
+ uniqueness_key.present?
39
+ end
40
+ end
41
+ end
@@ -4,6 +4,6 @@ Description:
4
4
  Example:
5
5
  bin/rails generate solid_queue:install
6
6
 
7
- This will create:
7
+ This will perform the following:
8
8
  Installs solid_queue migrations
9
- Replaces Active Job's adapter in envionment configuration
9
+ Replaces Active Job's adapter in environment configuration
@@ -1,4 +1,4 @@
1
- #default: &default
1
+ # default: &default
2
2
  # dispatchers:
3
3
  # - polling_interval: 1
4
4
  # batch_size: 500
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SolidQueue
4
+ class Dispatcher::ScheduledExecutionsDispatcher < Dispatcher
5
+ end
6
+ end
@@ -4,6 +4,8 @@ module SolidQueue::Processes
4
4
  module Runnable
5
5
  include Supervised
6
6
 
7
+ attr_writer :mode
8
+
7
9
  def start
8
10
  @stopping = false
9
11
 
@@ -19,8 +21,6 @@ module SolidQueue::Processes
19
21
  end
20
22
 
21
23
  private
22
- attr_writer :mode
23
-
24
24
  DEFAULT_MODE = :async
25
25
 
26
26
  def mode
@@ -1,3 +1,3 @@
1
1
  module SolidQueue
2
- VERSION = "0.2.0"
2
+ VERSION = "0.2.1"
3
3
  end
@@ -44,7 +44,7 @@ module SolidQueue
44
44
  end
45
45
 
46
46
  def all_work_completed?
47
- SolidQueue::ReadyExecution.queued_as(queues).empty?
47
+ SolidQueue::ReadyExecution.aggregated_count_across(queues).zero?
48
48
  end
49
49
 
50
50
  def metadata
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: solid_queue
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rosa Gutierrez
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-12-26 00:00:00.000000000 Z
11
+ date: 2024-01-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -79,6 +79,7 @@ files:
79
79
  - app/models/solid_queue/blocked_execution.rb
80
80
  - app/models/solid_queue/claimed_execution.rb
81
81
  - app/models/solid_queue/execution.rb
82
+ - app/models/solid_queue/execution/dispatching.rb
82
83
  - app/models/solid_queue/execution/job_attributes.rb
83
84
  - app/models/solid_queue/failed_execution.rb
84
85
  - app/models/solid_queue/job.rb
@@ -97,8 +98,10 @@ files:
97
98
  - app/models/solid_queue/semaphore.rb
98
99
  - config/routes.rb
99
100
  - db/migrate/20231211200639_create_solid_queue_tables.rb
101
+ - db/migrate/20240110143450_add_missing_index_to_blocked_executions.rb
100
102
  - lib/active_job/concurrency_controls.rb
101
103
  - lib/active_job/queue_adapters/solid_queue_adapter.rb
104
+ - lib/active_job/uniqueness.rb
102
105
  - lib/generators/solid_queue/install/USAGE
103
106
  - lib/generators/solid_queue/install/install_generator.rb
104
107
  - lib/generators/solid_queue/install/templates/config.yml
@@ -107,6 +110,7 @@ files:
107
110
  - lib/solid_queue/app_executor.rb
108
111
  - lib/solid_queue/configuration.rb
109
112
  - lib/solid_queue/dispatcher.rb
113
+ - lib/solid_queue/dispatcher/scheduled_executions_dispatcher.rb
110
114
  - lib/solid_queue/engine.rb
111
115
  - lib/solid_queue/pool.rb
112
116
  - lib/solid_queue/processes/base.rb