solid_queue 0.1.2 → 0.2.0

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: 2e1ff04f60a3eee3be19e692691ef7a70cd1cfc1a2edd5f019f6bbab9b8614e6
4
- data.tar.gz: bc96a464a966379d434b4e8c45c4ad24c30bf3aeed6d3b6acc60d94e1386a14e
3
+ metadata.gz: 72d9dc2e30127c7b1fe101648d4d18b04af2d33491c729816e25dcf488246b54
4
+ data.tar.gz: e39dcad251d4124355adcedfa9cb1ee88eea12043eb8505568332d9fcacee428
5
5
  SHA512:
6
- metadata.gz: 27d7bf13f3342cfccd54aa3cc3db18284d68b7fc56ae62b2c9ca66710aadb0eb8e37c48b8b268169fa37aac523cbe1cdb2dd7146fd160499d82e4521cb35d2ba
7
- data.tar.gz: df8f520b23ab98bdcea47ffab06df3bfa1e946072070d251ecd0d5e44a6f7e723fdd6278344b4dbf88a8d184ce661f97440ba188267d004df83a5df66945bedc
6
+ metadata.gz: 967732a5e679269543869ca64aa410bfc43c935ad3fb6856de0860bbe5cee58716e389b5935e48a91c6c658a84fa79aff9f5eae93ba3931344d31aff0d45c8fc
7
+ data.tar.gz: 523af9f1b26a137d99ade0805bdc955cb81584971308928d5e16e83d3c46861947deaaa95ff96775d7eceb913f3d8995eca14707cda4533f7c3ee39f20afb650
data/README.md CHANGED
@@ -2,29 +2,11 @@
2
2
 
3
3
  Solid Queue is a DB-based queuing backend for [Active Job](https://edgeguides.rubyonrails.org/active_job_basics.html), designed with simplicity and performance in mind.
4
4
 
5
- Besides regular job enqueuing and processing, Solid Queue supports delayed jobs, concurrency controls, pausing queues, numeric priorities per job, and priorities by queue order. _Proper support for `perform_all_later`, improvements to logging and instrumentation, a better CLI tool, a way to run within an existing process in "async" mode, unique jobs and recurring, cron-like tasks are coming very soon._
5
+ Besides regular job enqueuing and processing, Solid Queue supports delayed jobs, concurrency controls, pausing queues, numeric priorities per job, priorities by queue order, and bulk enqueuing (`enqueue_all` for Active Job's `perform_all_later`). _Improvements to logging and instrumentation, a better CLI tool, a way to run within an existing process in "async" mode, unique jobs and recurring, cron-like tasks are coming very soon._
6
6
 
7
7
  Solid Queue can be used with SQL databases such as MySQL, PostgreSQL or SQLite, and it leverages the `FOR UPDATE SKIP LOCKED` clause, if available, to avoid blocking and waiting on locks when polling jobs. It relies on Active Job for retries, discarding, error handling, serialization, or delays, and it's compatible with Ruby on Rails multi-threading.
8
8
 
9
- ## Usage
10
- To set Solid Queue as your Active Job's queue backend, you should add this to your environment config:
11
- ```ruby
12
- # config/environments/production.rb
13
- config.active_job.queue_adapter = :solid_queue
14
- ```
15
-
16
- Alternatively, you can set only specific jobs to use Solid Queue as their backend if you're migrating from another adapter and want to move jobs progressively:
17
-
18
- ```ruby
19
- # app/jobs/my_job.rb
20
-
21
- class MyJob < ApplicationJob
22
- self.queue_adapter = :solid_queue
23
- # ...
24
- end
25
- ```
26
-
27
- ## Installation
9
+ ## Installation and usage
28
10
  Add this line to your application's Gemfile:
29
11
 
30
12
  ```ruby
@@ -41,23 +23,43 @@ Or install it yourself as:
41
23
  $ gem install solid_queue
42
24
  ```
43
25
 
44
- Install Migrations and Set Up Active Job Adapter
45
- Now, you need to install the necessary migrations and configure the Active Job's adapter. Run the following commands:
26
+ Now, you need to install the necessary migrations and configure the Active Job's adapter. You can do both at once using the provided generator:
27
+
46
28
  ```bash
47
29
  $ bin/rails generate solid_queue:install
48
30
  ```
49
31
 
50
- or add the only the migration to your app and run it:
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
+
34
+ Alternatively, you can add the only the migration to your app:
51
35
  ```bash
52
36
  $ bin/rails solid_queue:install:migrations
53
37
  ```
54
38
 
55
- Run the Migrations (required after either of the above steps):
39
+ And set Solid Queue as your Active Job's queue backend manually, in your environment config:
40
+ ```ruby
41
+ # config/environments/production.rb
42
+ config.active_job.queue_adapter = :solid_queue
43
+ ```
44
+
45
+ Alternatively, you can set only specific jobs to use Solid Queue as their backend if you're migrating from another adapter and want to move jobs progressively:
46
+
47
+ ```ruby
48
+ # app/jobs/my_job.rb
49
+
50
+ class MyJob < ApplicationJob
51
+ self.queue_adapter = :solid_queue
52
+ # ...
53
+ end
54
+ ```
55
+
56
+ Finally, you need to run the migrations:
57
+
56
58
  ```bash
57
59
  $ bin/rails db:migrate
58
60
  ```
59
61
 
60
- With this, you'll be ready to enqueue jobs using Solid Queue, but you need to start Solid Queue's supervisor to run them.
62
+ After this, you'll be ready to enqueue jobs using Solid Queue, but you need to start Solid Queue's supervisor to run them.
61
63
  ```bash
62
64
  $ bundle exec rake solid_queue:start
63
65
  ```
@@ -65,7 +67,7 @@ $ bundle exec rake solid_queue:start
65
67
  This will start processing jobs in all queues using the default configuration. See [below](#configuration) to learn more about configuring Solid Queue.
66
68
 
67
69
  ## Requirements
68
- Besides Rails 7, Solid Queue works best with MySQL 8+ or PostgreSQL 9.5+, as they support `FOR UPDATE SKIP LOCKED`. You can use it with older versions, but in that case, you might run into lock waits if you run multiple workers for the same queue.
70
+ Besides Rails 7.1, Solid Queue works best with MySQL 8+ or PostgreSQL 9.5+, as they support `FOR UPDATE SKIP LOCKED`. You can use it with older versions, but in that case, you might run into lock waits if you run multiple workers for the same queue.
69
71
 
70
72
  ## Configuration
71
73
 
@@ -83,6 +85,7 @@ production:
83
85
  dispatchers:
84
86
  - polling_interval: 1
85
87
  batch_size: 500
88
+ concurrency_maintenance_interval: 300
86
89
  workers:
87
90
  - queues: "*"
88
91
  threads: 3
@@ -97,6 +100,7 @@ Everything is optional. If no configuration is provided, Solid Queue will run wi
97
100
 
98
101
  - `polling_interval`: the time interval in seconds that workers and dispatchers will wait before checking for more jobs. This time defaults to `1` second for dispatchers and `0.1` seconds for workers.
99
102
  - `batch_size`: the dispatcher will dispatch jobs in batches of this size. The default is 500.
103
+ - `concurrency_maintenance_interval`: the time interval in seconds that the dispatcher will wait before checking for blocked jobs that can be unblocked. Read more about [concurrency controls](#concurrency-controls) to learn more about this setting. It defaults to `600` seconds.
100
104
  - `queues`: the list of queues that workers will pick jobs from. You can use `*` to indicate all queues (which is also the default and the behaviour you'll get if you omit this). You can provide a single queue, or a list of queues as an array. Jobs will be polled from those queues in order, so for example, with `[ real_time, background ]`, no jobs will be taken from `background` unless there aren't any more jobs waiting in `real_time`. You can also provide a prefix with a wildcard to match queues starting with a prefix. For example:
101
105
 
102
106
  ```yml
@@ -2,7 +2,7 @@
2
2
 
3
3
  module SolidQueue
4
4
  class BlockedExecution < Execution
5
- assume_attributes_from_job :concurrency_key
5
+ assumes_attributes_from_job :concurrency_key
6
6
  before_create :set_expires_at
7
7
 
8
8
  has_one :semaphore, foreign_key: :key, primary_key: :concurrency_key
@@ -5,17 +5,24 @@ module SolidQueue
5
5
  module JobAttributes
6
6
  extend ActiveSupport::Concern
7
7
 
8
- ASSUMIBLE_ATTRIBUTES_FROM_JOB = %i[ queue_name priority ]
8
+ included do
9
+ class_attribute :assumible_attributes_from_job, instance_accessor: false, default: %i[ queue_name priority ]
10
+ end
9
11
 
10
12
  class_methods do
11
- def assume_attributes_from_job(*attributes)
12
- before_create -> { assume_attributes_from_job(ASSUMIBLE_ATTRIBUTES_FROM_JOB | attributes) }
13
+ def assumes_attributes_from_job(*attribute_names)
14
+ self.assumible_attributes_from_job |= attribute_names
15
+ before_create -> { assume_attributes_from_job }
16
+ end
17
+
18
+ def attributes_from_job(job)
19
+ job.attributes.symbolize_keys.slice(*assumible_attributes_from_job)
13
20
  end
14
21
  end
15
22
 
16
23
  private
17
- def assume_attributes_from_job(attributes)
18
- attributes.each do |attribute|
24
+ def assume_attributes_from_job
25
+ self.class.assumible_attributes_from_job.each do |attribute|
19
26
  send("#{attribute}=", job.send(attribute))
20
27
  end
21
28
  end
@@ -11,5 +11,17 @@ module SolidQueue
11
11
  belongs_to :job
12
12
 
13
13
  alias_method :discard, :destroy
14
+
15
+ class << self
16
+ def create_all_from_jobs(jobs)
17
+ insert_all execution_data_from_jobs(jobs)
18
+ end
19
+
20
+ def execution_data_from_jobs(jobs)
21
+ jobs.collect do |job|
22
+ attributes_from_job(job).merge(job_id: job.id)
23
+ end
24
+ end
25
+ end
14
26
  end
15
27
  end
@@ -1,11 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class SolidQueue::FailedExecution < SolidQueue::Execution
4
- if Gem::Version.new(Rails.version) >= Gem::Version.new("7.1")
5
- serialize :error, coder: JSON
6
- else
7
- serialize :error, JSON
8
- end
4
+ serialize :error, coder: JSON
9
5
 
10
6
  before_create :expand_error_details_from_exception
11
7
 
@@ -6,20 +6,56 @@ module SolidQueue
6
6
  extend ActiveSupport::Concern
7
7
 
8
8
  included do
9
- include Clearable, ConcurrencyControls
9
+ include Clearable, ConcurrencyControls, Schedulable
10
10
 
11
11
  has_one :ready_execution, dependent: :destroy
12
12
  has_one :claimed_execution, dependent: :destroy
13
13
  has_one :failed_execution, dependent: :destroy
14
14
 
15
- has_one :scheduled_execution, dependent: :destroy
16
-
17
15
  after_create :prepare_for_execution
18
16
 
19
17
  scope :finished, -> { where.not(finished_at: nil) }
18
+ scope :failed, -> { includes(:failed_execution).where.not(failed_execution: { id: nil }) }
20
19
  end
21
20
 
22
- %w[ ready claimed failed scheduled ].each do |status|
21
+ class_methods do
22
+ def prepare_all_for_execution(jobs)
23
+ due, not_yet_due = jobs.partition(&:due?)
24
+ dispatch_all(due) + schedule_all(not_yet_due)
25
+ end
26
+
27
+ def dispatch_all(jobs)
28
+ with_concurrency_limits, without_concurrency_limits = jobs.partition(&:concurrency_limited?)
29
+
30
+ dispatch_all_at_once(without_concurrency_limits)
31
+ dispatch_all_one_by_one(with_concurrency_limits)
32
+
33
+ successfully_dispatched(jobs)
34
+ end
35
+
36
+ private
37
+ def dispatch_all_at_once(jobs)
38
+ ReadyExecution.create_all_from_jobs jobs
39
+ end
40
+
41
+ def dispatch_all_one_by_one(jobs)
42
+ jobs.each(&:dispatch)
43
+ end
44
+
45
+ def successfully_dispatched(jobs)
46
+ dispatched_and_ready(jobs) + dispatched_and_blocked(jobs)
47
+ end
48
+
49
+ def dispatched_and_ready(jobs)
50
+ where(id: ReadyExecution.where(job_id: jobs.map(&:id)).pluck(:job_id))
51
+ end
52
+
53
+ def dispatched_and_blocked(jobs)
54
+ where(id: BlockedExecution.where(job_id: jobs.map(&:id)).pluck(:job_id))
55
+ end
56
+ end
57
+
58
+ %w[ ready claimed failed ].each do |status|
23
59
  define_method("#{status}?") { public_send("#{status}_execution").present? }
24
60
  end
25
61
 
@@ -49,8 +85,8 @@ module SolidQueue
49
85
  finished_at.present?
50
86
  end
51
87
 
52
- def failed_with(exception)
53
- FailedExecution.create_or_find_by!(job_id: id, exception: exception)
88
+ def due?
89
+ scheduled_at.nil? || scheduled_at <= Time.current
54
90
  end
55
91
 
56
92
  def discard
@@ -66,14 +102,6 @@ module SolidQueue
66
102
  end
67
103
 
68
104
  private
69
- def due?
70
- scheduled_at.nil? || scheduled_at <= Time.current
71
- end
72
-
73
- def schedule
74
- ScheduledExecution.create_or_find_by!(job_id: id)
75
- end
76
-
77
105
  def ready
78
106
  ReadyExecution.create_or_find_by!(job_id: id)
79
107
  end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SolidQueue
4
+ class Job
5
+ module Schedulable
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ has_one :scheduled_execution, dependent: :destroy
10
+
11
+ scope :scheduled, -> { where.not(finished_at: nil) }
12
+ end
13
+
14
+ class_methods do
15
+ def schedule_all(jobs)
16
+ schedule_all_at_once(jobs)
17
+ successfully_scheduled(jobs)
18
+ end
19
+
20
+ private
21
+ def schedule_all_at_once(jobs)
22
+ ScheduledExecution.create_all_from_jobs(jobs)
23
+ end
24
+
25
+ def successfully_scheduled(jobs)
26
+ where(id: ScheduledExecution.where(job_id: jobs.map(&:id)).pluck(:job_id))
27
+ end
28
+ end
29
+
30
+ def due?
31
+ scheduled_at.nil? || scheduled_at <= Time.current
32
+ end
33
+
34
+ private
35
+ def schedule
36
+ ScheduledExecution.create_or_find_by!(job_id: id)
37
+ end
38
+ end
39
+ end
40
+ end
@@ -1,38 +1,58 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class SolidQueue::Job < SolidQueue::Record
4
- include Executable
3
+ module SolidQueue
4
+ class Job < Record
5
+ include Executable
5
6
 
6
- if Gem::Version.new(Rails.version) >= Gem::Version.new("7.1")
7
7
  serialize :arguments, coder: JSON
8
- else
9
- serialize :arguments, JSON
10
- end
11
8
 
12
- DEFAULT_PRIORITY = 0
13
- DEFAULT_QUEUE_NAME = "default"
14
-
15
- class << self
16
- def enqueue_active_job(active_job, scheduled_at: Time.current)
17
- enqueue \
18
- queue_name: active_job.queue_name,
19
- active_job_id: active_job.job_id,
20
- priority: active_job.priority,
21
- scheduled_at: scheduled_at,
22
- class_name: active_job.class.name,
23
- arguments: active_job.serialize,
24
- concurrency_key: active_job.try(:concurrency_key)
25
- end
9
+ class << self
10
+ def enqueue_all(active_jobs)
11
+ active_jobs_by_job_id = active_jobs.index_by(&:job_id)
26
12
 
27
- def enqueue(**kwargs)
28
- create!(**kwargs.compact.with_defaults(defaults)).tap do
29
- SolidQueue.logger.debug "[SolidQueue] Enqueued job #{kwargs}"
13
+ transaction do
14
+ jobs = create_all_from_active_jobs(active_jobs)
15
+ prepare_all_for_execution(jobs).tap do |enqueued_jobs|
16
+ enqueued_jobs.each do |enqueued_job|
17
+ active_jobs_by_job_id[enqueued_job.active_job_id].provider_job_id = enqueued_job.id
18
+ end
19
+ end
20
+ end
30
21
  end
31
- end
32
22
 
33
- private
34
- def defaults
35
- { queue_name: DEFAULT_QUEUE_NAME, priority: DEFAULT_PRIORITY }
23
+ def enqueue(active_job, scheduled_at: Time.current)
24
+ active_job.scheduled_at = scheduled_at
25
+
26
+ create_from_active_job(active_job).tap do |enqueued_job|
27
+ active_job.provider_job_id = enqueued_job.id
28
+ end
36
29
  end
30
+
31
+ private
32
+ DEFAULT_PRIORITY = 0
33
+ DEFAULT_QUEUE_NAME = "default"
34
+
35
+ def create_from_active_job(active_job)
36
+ create!(**attributes_from_active_job(active_job))
37
+ end
38
+
39
+ def create_all_from_active_jobs(active_jobs)
40
+ job_rows = active_jobs.map { |job| attributes_from_active_job(job) }
41
+ insert_all(job_rows)
42
+ where(active_job_id: active_jobs.map(&:job_id))
43
+ end
44
+
45
+ def attributes_from_active_job(active_job)
46
+ {
47
+ queue_name: active_job.queue_name || DEFAULT_QUEUE_NAME,
48
+ active_job_id: active_job.job_id,
49
+ priority: active_job.priority || DEFAULT_PRIORITY,
50
+ scheduled_at: active_job.scheduled_at,
51
+ class_name: active_job.class.name,
52
+ arguments: active_job.serialize,
53
+ concurrency_key: active_job.concurrency_key
54
+ }
55
+ end
56
+ end
37
57
  end
38
58
  end
@@ -4,7 +4,7 @@ module SolidQueue
4
4
  class ReadyExecution < Execution
5
5
  scope :queued_as, ->(queue_name) { where(queue_name: queue_name) }
6
6
 
7
- assume_attributes_from_job
7
+ assumes_attributes_from_job
8
8
 
9
9
  class << self
10
10
  def claim(queue_list, limit, process_id)
@@ -6,7 +6,7 @@ module SolidQueue
6
6
  scope :ordered, -> { order(scheduled_at: :asc, priority: :asc) }
7
7
  scope :next_batch, ->(batch_size) { due.ordered.limit(batch_size) }
8
8
 
9
- assume_attributes_from_job :scheduled_at
9
+ assumes_attributes_from_job :scheduled_at
10
10
 
11
11
  class << self
12
12
  def dispatch_next_batch(batch_size)
@@ -22,44 +22,12 @@ module SolidQueue
22
22
  private
23
23
  def dispatch_batch(job_ids)
24
24
  jobs = Job.where(id: job_ids)
25
- with_concurrency_limits, without_concurrency_limits = jobs.partition(&:concurrency_limited?)
26
25
 
27
- dispatch_at_once(without_concurrency_limits)
28
- dispatch_one_by_one(with_concurrency_limits)
29
-
30
- successfully_dispatched(job_ids).tap do |dispatched_job_ids|
26
+ Job.dispatch_all(jobs).map(&:id).tap do |dispatched_job_ids|
31
27
  where(job_id: dispatched_job_ids).delete_all
32
28
  SolidQueue.logger.info("[SolidQueue] Dispatched scheduled batch with #{dispatched_job_ids.size} jobs")
33
29
  end
34
30
  end
35
-
36
- def dispatch_at_once(jobs)
37
- ReadyExecution.insert_all ready_rows_from_batch(jobs)
38
- end
39
-
40
- def dispatch_one_by_one(jobs)
41
- jobs.each(&:dispatch)
42
- end
43
-
44
- def ready_rows_from_batch(jobs)
45
- prepared_at = Time.current
46
-
47
- jobs.map do |job|
48
- { job_id: job.id, queue_name: job.queue_name, priority: job.priority, created_at: prepared_at }
49
- end
50
- end
51
-
52
- def successfully_dispatched(job_ids)
53
- dispatched_and_ready(job_ids) + dispatched_and_blocked(job_ids)
54
- end
55
-
56
- def dispatched_and_ready(job_ids)
57
- ReadyExecution.where(job_id: job_ids).pluck(:job_id)
58
- end
59
-
60
- def dispatched_and_blocked(job_ids)
61
- BlockedExecution.where(job_id: job_ids).pluck(:job_id)
62
- end
63
31
  end
64
32
  end
65
33
  end
@@ -36,6 +36,10 @@ module ActiveJob
36
36
  end
37
37
  end
38
38
 
39
+ def concurrency_limited?
40
+ concurrency_key.present?
41
+ end
42
+
39
43
  private
40
44
  def concurrency_group
41
45
  compute_concurrency_parameter(self.class.concurrency_group)
@@ -9,15 +9,15 @@ module ActiveJob
9
9
  # Rails.application.config.active_job.queue_adapter = :solid_queue
10
10
  class SolidQueueAdapter
11
11
  def enqueue(active_job) # :nodoc:
12
- SolidQueue::Job.enqueue_active_job(active_job).tap do |job|
13
- active_job.provider_job_id = job.id
14
- end
12
+ SolidQueue::Job.enqueue(active_job)
15
13
  end
16
14
 
17
15
  def enqueue_at(active_job, timestamp) # :nodoc:
18
- SolidQueue::Job.enqueue_active_job(active_job, scheduled_at: Time.at(timestamp)).tap do |job|
19
- active_job.provider_job_id = job.id
20
- end
16
+ SolidQueue::Job.enqueue(active_job, scheduled_at: Time.at(timestamp))
17
+ end
18
+
19
+ def enqueue_all(active_jobs) # :nodoc:
20
+ SolidQueue::Job.enqueue_all(active_jobs)
21
21
  end
22
22
  end
23
23
  end
@@ -6,10 +6,8 @@ class SolidQueue::InstallGenerator < Rails::Generators::Base
6
6
  class_option :skip_migrations, type: :boolean, default: nil, desc: "Skip migrations"
7
7
 
8
8
  def add_solid_queue
9
- %w[ development test production ].each do |env_name|
10
- if (env_config = Pathname(destination_root).join("config/environments/#{env_name}.rb")).exist?
11
- gsub_file env_config, /(# )?config\.active_job\.queue_adapter\s+=.*/, "config.active_job.queue_adapter = :solid_queue"
12
- end
9
+ if (env_config = Pathname(destination_root).join("config/environments/production.rb")).exist?
10
+ gsub_file env_config, /(# )?config\.active_job\.queue_adapter\s+=.*/, "config.active_job.queue_adapter = :solid_queue"
13
11
  end
14
12
 
15
13
  copy_file "config.yml", "config/solid_queue.yml"
@@ -6,16 +6,19 @@ Puma::Plugin.create do
6
6
  def start(launcher)
7
7
  @log_writer = launcher.log_writer
8
8
  @puma_pid = $$
9
- @solid_queue_pid = fork do
10
- Thread.new { monitor_puma }
11
- SolidQueue::Supervisor.start(mode: :all)
12
- end
13
9
 
14
- launcher.events.on_stopped { stop_solid_queue }
10
+ launcher.events.on_booted do
11
+ @solid_queue_pid = fork do
12
+ Thread.new { monitor_puma }
13
+ SolidQueue::Supervisor.start(mode: :all)
14
+ end
15
15
 
16
- in_background do
17
- monitor_solid_queue
16
+ in_background do
17
+ monitor_solid_queue
18
+ end
18
19
  end
20
+
21
+ launcher.events.on_stopped { stop_solid_queue }
19
22
  end
20
23
 
21
24
  private
@@ -44,7 +44,9 @@ module SolidQueue::Processes
44
44
  loop do
45
45
  break if shutting_down?
46
46
 
47
- run
47
+ wrap_in_app_executor do
48
+ run
49
+ end
48
50
  end
49
51
  ensure
50
52
  run_callbacks(:shutdown) { shutdown }
@@ -1,3 +1,3 @@
1
1
  module SolidQueue
2
- VERSION = "0.1.2"
2
+ VERSION = "0.2.0"
3
3
  end
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: solid_queue
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0
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-21 00:00:00.000000000 Z
11
+ date: 2023-12-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 7.0.3.1
19
+ version: '7.1'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ">="
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 7.0.3.1
26
+ version: '7.1'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: debug
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: puma
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
55
69
  description: Database-backed Active Job backend.
56
70
  email:
57
71
  - rosa@37signals.com
@@ -71,6 +85,7 @@ files:
71
85
  - app/models/solid_queue/job/clearable.rb
72
86
  - app/models/solid_queue/job/concurrency_controls.rb
73
87
  - app/models/solid_queue/job/executable.rb
88
+ - app/models/solid_queue/job/schedulable.rb
74
89
  - app/models/solid_queue/pause.rb
75
90
  - app/models/solid_queue/process.rb
76
91
  - app/models/solid_queue/process/prunable.rb
@@ -128,7 +143,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
128
143
  - !ruby/object:Gem::Version
129
144
  version: '0'
130
145
  requirements: []
131
- rubygems_version: 3.4.20
146
+ rubygems_version: 3.4.10
132
147
  signing_key:
133
148
  specification_version: 4
134
149
  summary: Database-backed Active Job backend.