solid_queue 1.2.0 → 1.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: 1d0b2a7e3a5ad6577d52d3528f42ff8862c087f6f406d0f6fd96f12f36db6795
4
- data.tar.gz: 4db8708635736bd5ccb32ad619577494c039574fd452a40c3fecc55d0f57c27b
3
+ metadata.gz: 9066bd5266e43075385bfd3365de2512400960f5cfa7f780dba69e4a3259c07a
4
+ data.tar.gz: 0a7103f485e445563814874e3113b6ac6dca84c8333bad418c449ebaf3fac1c9
5
5
  SHA512:
6
- metadata.gz: 2ba5bb04f334bcc56bb0504d0baac497287058c242aaf8fccd85c72e1c72c5107ad38eff211d9c16641a3cc7ad366673a316cf357daf70bdf97009d68b7c5646
7
- data.tar.gz: bf7770477e8dd290bd9461bcc5202b5d0832639ed31e7df7e96d192562fe5c0574522f1f689504c6d98c44c14ba389597bd7627fe3ec76c1e76937c0f0eaaac7
6
+ metadata.gz: 952b71b5cd59ebd79eb51c44f7ed509bf3d4959c010dc0441cff37c0a1bd2ccea97054007bd3a197b287a158342e8791318c841f0d1d9b3dd347986da68bb53a
7
+ data.tar.gz: 1309ce242499f430667d9677b7ff8807e1b43af33873d9b00575c4c9e13be24824d9520ca24db432901da2616c4ba5a530db83fd29c09c47b820fff3586a75b7
data/README.md CHANGED
@@ -433,7 +433,9 @@ In the case of recurring tasks, if such error is raised when enqueuing the job c
433
433
 
434
434
  ## Concurrency controls
435
435
 
436
- Solid Queue extends Active Job with concurrency controls, that allows you to limit how many jobs of a certain type or with certain arguments can run at the same time. When limited in this way, by default, jobs will be blocked from running, and they'll stay blocked until another job finishes and unblocks them, or after the set expiry time (concurrency limit's _duration_) elapses. Alternatively, jobs can be configured to be discarded instead of blocked. This means that if a job with certain arguments has already been enqueued, other jobs with the same characteristics (in the same concurrency _class_) won't be enqueued.
436
+ Solid Queue extends Active Job with concurrency controls, that allows you to limit how many jobs of a certain type or with certain arguments can run at the same time. When limited in this way, **by default, jobs will be blocked from running**, and they'll stay blocked until another job finishes and unblocks them, or after the set expiry time (concurrency limit's _duration_) elapses.
437
+
438
+ **Alternatively, jobs can be configured to be discarded instead of blocked**. This means that if a job with certain arguments has already been enqueued, other jobs with the same characteristics (in the same concurrency _class_) won't be enqueued.
437
439
 
438
440
  ```ruby
439
441
  class MyJob < ApplicationJob
@@ -496,6 +498,29 @@ Jobs are unblocked in order of priority but **queue order is not taken into acco
496
498
 
497
499
  Finally, failed jobs that are automatically or manually retried work in the same way as new jobs that get enqueued: they get in the queue for getting an open semaphore, and whenever they get it, they'll be run. It doesn't matter if they had already gotten an open semaphore in the past.
498
500
 
501
+ ### Scheduled jobs
502
+
503
+ Jobs set to run in the future (via Active Job's `wait` or `wait_until` options) have concurrency limits enforced when they're due, not when they're scheduled. For example, consider this job:
504
+ ```ruby
505
+ class DeliverAnnouncementToContactJob < ApplicationJob
506
+ limits_concurrency to: 1, key: ->(contact) { contact.account }, duration: 5.minutes
507
+
508
+ def perform(contact)
509
+ # ...
510
+ ```
511
+
512
+ If several jobs are enqueued like this:
513
+
514
+ ```ruby
515
+ DeliverAnnouncementToContactJob.set(wait: 10.minutes).perform_later(contact)
516
+ DeliverAnnouncementToContactJob.set(wait: 10.minutes).perform_later(contact)
517
+ DeliverAnnouncementToContactJob.set(wait: 30.minutes).perform_later(contact)
518
+ ```
519
+
520
+ The 3 jobs will go into the scheduled queue and will wait there until they're due. Then, 10 minutes after, the first two jobs will be enqueued and the second one most likely will be blocked because the first one will be running first. Then, assuming the jobs are fast and finish in a few seconds, when the third job is due, it'll be enqueued normally.
521
+
522
+ Normally scheduled jobs are enqueued in batches, but with concurrency controls, jobs need to be enqueued one by one. This has an impact on performance, similarly to the impact of concurrency controls in bulk enqueuing. Read below for more details. I'd generally advise against mixing concurrency controls with waiting/scheduling in the future.
523
+
499
524
  ### Performance considerations
500
525
 
501
526
  Concurrency controls introduce significant overhead (blocked executions need to be created and promoted to ready, semaphores need to be created and updated) so you should consider carefully whether you need them. For throttling purposes, where you plan to have `limit` significantly larger than 1, I'd encourage relying on a limited number of workers per queue instead. For example:
data/Rakefile CHANGED
@@ -8,14 +8,36 @@ load "rails/tasks/engine.rake"
8
8
  load "rails/tasks/statistics.rake"
9
9
 
10
10
  require "bundler/gem_tasks"
11
+ require "rake/tasklib"
11
12
 
12
- def databases
13
- %w[ mysql postgres sqlite ]
14
- end
13
+ class TestHelpers < Rake::TaskLib
14
+ def initialize(databases)
15
+ @databases = databases
16
+ define
17
+ end
15
18
 
16
- task :test do
17
- databases.each do |database|
19
+ def define
20
+ desc "Run tests for all databases (mysql, postgres, sqlite)"
21
+ task :test do
22
+ @databases.each { |database| run_test_for_database(database) }
23
+ end
24
+
25
+ namespace :test do
26
+ @databases.each do |database|
27
+ desc "Run tests for #{database} database"
28
+ task database do
29
+ run_test_for_database(database)
30
+ end
31
+ end
32
+ end
33
+ end
34
+
35
+ private
36
+
37
+ def run_test_for_database(database)
18
38
  sh("TARGET_DB=#{database} bin/setup")
19
39
  sh("TARGET_DB=#{database} bin/rails test")
20
40
  end
21
41
  end
42
+
43
+ TestHelpers.new(%w[ mysql postgres sqlite ])
@@ -30,6 +30,7 @@ module SolidQueue
30
30
 
31
31
  create_from_active_job(active_job).tap do |enqueued_job|
32
32
  active_job.provider_job_id = enqueued_job.id if enqueued_job.persisted?
33
+ active_job.successfully_enqueued = enqueued_job.persisted?
33
34
  end
34
35
  end
35
36
 
@@ -130,7 +130,6 @@ module SolidQueue
130
130
  active_job.run_callbacks(:enqueue) do
131
131
  Job.enqueue(active_job)
132
132
  end
133
- active_job.successfully_enqueued = true
134
133
  end
135
134
  end
136
135
  end
@@ -1,3 +1,3 @@
1
1
  module SolidQueue
2
- VERSION = "1.2.0"
2
+ VERSION = "1.2.1"
3
3
  end
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: 1.2.0
4
+ version: 1.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: 2025-07-11 00:00:00.000000000 Z
11
+ date: 2025-07-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -84,14 +84,14 @@ dependencies:
84
84
  name: thor
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - "~>"
87
+ - - ">="
88
88
  - !ruby/object:Gem::Version
89
89
  version: 1.3.1
90
90
  type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - "~>"
94
+ - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: 1.3.1
97
97
  - !ruby/object:Gem::Dependency