solid_queue 0.2.0 → 0.2.1

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: 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