postburner 1.0.0.pre.1 → 1.0.0.pre.3
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 +4 -4
- data/README.md +204 -117
- data/app/models/postburner/job.rb +12 -12
- data/app/models/postburner/mailer.rb +2 -2
- data/config/postburner.yml.example +32 -30
- data/lib/generators/postburner/install/install_generator.rb +10 -0
- data/lib/generators/postburner/install/templates/config/postburner.yml +144 -0
- data/lib/postburner/active_job/adapter.rb +22 -9
- data/lib/postburner/beanstalkd.rb +18 -39
- data/lib/postburner/configuration.rb +42 -15
- data/lib/postburner/queue_config.rb +25 -22
- data/lib/postburner/strategies/queue.rb +2 -2
- data/lib/postburner/version.rb +1 -1
- data/lib/postburner/workers/worker.rb +27 -28
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2f7e4e766eb885d932fe5949dc935b1efcb927894117cc427b7582e6807942f6
|
|
4
|
+
data.tar.gz: d9b2ed2f5fe0aa61cf0a28d1560f861619c3049aa0bb44fb43b6a6d662914ce8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4cb2922ca8f02625680f73232e4cc15590deecd1e6e7f792fda4b547cbb3b300de44107a055247a72ab5b56d0706631323149151708780dd9d719140255973f4
|
|
7
|
+
data.tar.gz: c749613be57e8ca5bf14671a2f8c4743e34e9839f4432305c12bfb35e34e4718b1319096ed7336fe5d083994b5da7047b706c55f3a1b735439be4bb6a28c4a55
|
data/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Postburner
|
|
2
2
|
|
|
3
|
-
Fast Beanstalkd-backed job queue with **optional PostgreSQL
|
|
3
|
+
Fast Beanstalkd-backed job queue with **optional PostgreSQL records** for ActiveJob.
|
|
4
4
|
|
|
5
5
|
Postburner provides dual-mode job execution:
|
|
6
6
|
- **Default jobs**: Fast execution via Beanstalkd only (no PostgreSQL overhead)
|
|
@@ -8,6 +8,22 @@ Postburner provides dual-mode job execution:
|
|
|
8
8
|
|
|
9
9
|
Built for production environments where you want fast background processing for most jobs, but comprehensive auditing for critical operations.
|
|
10
10
|
|
|
11
|
+
Depends on Beanstalkd, ActiveRecord, ActiveJob, Postgres.
|
|
12
|
+
|
|
13
|
+
## Why
|
|
14
|
+
|
|
15
|
+
Postburner supports Async, Queues, Delayed, Priorities, Timeouts, and Retries from the [Backend Matrix](https://api.rubyonrails.org/classes/ActiveJob/QueueAdapters.html). But uniquely, priorities are per job, in addition to the class level. Timeouts are per job and class level as well, and can be extended dynamically.
|
|
16
|
+
|
|
17
|
+
Postburner is inspired by the [Backburner](https://github.com/nesquena/backburner) gem i.e. "burner", Postgres i.e. "Post", and the database backends (SolidQueue, Que, etc), and the in memory/redis backends (Sidekiq, Resque, etc). And puma's concurrency model.
|
|
18
|
+
|
|
19
|
+
Thus old-school [beanstalkd](https://beanstalkd.github.io/) is used with PostgreSQL to cover all the cases we care about.
|
|
20
|
+
- Fast when you want it (light, ephemeral jobs like delayed turbo_stream rendering, communications)
|
|
21
|
+
- Tracked when you need it (critical operations like payments, and processes.
|
|
22
|
+
- Able to record jobs before and after execution in PostgreSQL, with foreign keys and constraints.
|
|
23
|
+
- Store the jobs outside of the database, but also persist them to disk for disaster recovery (beanstalkd binlogs)
|
|
24
|
+
- Introspect the jobs either with ActiveRecord or Beanstalkd.
|
|
25
|
+
- Only one worker type, that can be single/multi-process, with optional threading, and optional GC (Garbage Collection) limits (kill fork after processing N jobs).
|
|
26
|
+
|
|
11
27
|
## Features
|
|
12
28
|
|
|
13
29
|
- **ActiveJob native** - Works seamlessly with Rails, ActionMailer, ActiveStorage
|
|
@@ -20,8 +36,6 @@ Built for production environments where you want fast background processing for
|
|
|
20
36
|
|
|
21
37
|
## Quick Start
|
|
22
38
|
|
|
23
|
-
**Installation:**
|
|
24
|
-
|
|
25
39
|
```bash
|
|
26
40
|
sudo apt-get install beanstalkd # OR brew install beanstalkd
|
|
27
41
|
|
|
@@ -35,17 +49,14 @@ beanstalkd -l 127.0.0.1 -p 11300 -b /var/lib/beanstalkd
|
|
|
35
49
|
|
|
36
50
|
```ruby
|
|
37
51
|
# Gemfile
|
|
38
|
-
gem 'postburner', '~> 1.0.0.pre.
|
|
52
|
+
gem 'postburner', '~> 1.0.0.pre.2'
|
|
39
53
|
```
|
|
40
54
|
|
|
41
55
|
```bash
|
|
42
|
-
bundle install
|
|
43
56
|
rails generate postburner:install
|
|
44
57
|
rails db:migrate
|
|
45
58
|
```
|
|
46
59
|
|
|
47
|
-
**Configuration:**
|
|
48
|
-
|
|
49
60
|
```ruby
|
|
50
61
|
# config/application.rb
|
|
51
62
|
config.active_job.queue_adapter = :postburner
|
|
@@ -53,34 +64,56 @@ config.active_job.queue_adapter = :postburner
|
|
|
53
64
|
|
|
54
65
|
```yaml
|
|
55
66
|
# config/postburner.yml
|
|
56
|
-
production:
|
|
67
|
+
production: # <- environment config, i.e. defaults
|
|
57
68
|
beanstalk_url: <%= ENV['BEANSTALK_URL'] || 'beanstalk://localhost:11300' %>
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
69
|
+
default_forks: 2
|
|
70
|
+
default_threads: 10
|
|
71
|
+
default_gc_limit: 500
|
|
72
|
+
|
|
73
|
+
workers: # <- worker config, i.e. overrides
|
|
74
|
+
default:
|
|
75
|
+
threads: 16 # Overrides default_threads
|
|
76
|
+
queues:
|
|
77
|
+
- default
|
|
78
|
+
- mailers
|
|
79
|
+
critical:
|
|
80
|
+
forks: 4 # Overrides default_forks
|
|
81
|
+
threads: 8 # Overrides default_threads
|
|
82
|
+
gc_limit: 24 # Overrides default_gc_limit
|
|
83
|
+
queues:
|
|
84
|
+
- payments
|
|
85
|
+
slow:
|
|
86
|
+
forks: 4 # Overrides default_forks
|
|
87
|
+
threads: 1 # Overrides default_threads
|
|
88
|
+
gc_limit: 1 # Overrides default_gc_limit
|
|
89
|
+
queues:
|
|
90
|
+
- imports
|
|
91
|
+
- video
|
|
63
92
|
```
|
|
64
93
|
|
|
65
94
|
**Usage:**
|
|
66
95
|
|
|
67
96
|
```ruby
|
|
68
97
|
# Default job (fast, no PostgreSQL overhead)
|
|
69
|
-
class
|
|
98
|
+
class SendSms < ApplicationJob
|
|
70
99
|
def perform(user_id)
|
|
71
|
-
|
|
100
|
+
user = User.find(user_id)
|
|
101
|
+
TextMessage.welcome(
|
|
102
|
+
to: user.phone_number,
|
|
103
|
+
body: "Welcome to our app!"
|
|
104
|
+
).deliver_now
|
|
72
105
|
end
|
|
73
106
|
end
|
|
74
107
|
|
|
75
108
|
# Default job with Beanstalkd configuration
|
|
76
|
-
class
|
|
77
|
-
include Postburner::Beanstalkd
|
|
109
|
+
class DoSomething < ApplicationJob
|
|
110
|
+
include Postburner::Beanstalkd # optional, allow access to beanstalkd
|
|
78
111
|
|
|
79
|
-
|
|
80
|
-
|
|
112
|
+
priority 5000 # 0=highest, 65536=default, can set per job
|
|
113
|
+
ttr 30 # 30 second timeout
|
|
81
114
|
|
|
82
115
|
def perform(user_id)
|
|
83
|
-
|
|
116
|
+
# Do something
|
|
84
117
|
end
|
|
85
118
|
end
|
|
86
119
|
|
|
@@ -88,8 +121,8 @@ end
|
|
|
88
121
|
class ProcessPayment < ApplicationJob
|
|
89
122
|
include Postburner::Tracked # ← Opt-in to tracking (includes Beanstalkd)
|
|
90
123
|
|
|
91
|
-
|
|
92
|
-
|
|
124
|
+
priority 0 # Highest priority
|
|
125
|
+
ttr 600 # 10 minute timeout
|
|
93
126
|
|
|
94
127
|
def perform(payment_id)
|
|
95
128
|
log "Processing payment #{payment_id}"
|
|
@@ -99,7 +132,7 @@ class ProcessPayment < ApplicationJob
|
|
|
99
132
|
end
|
|
100
133
|
|
|
101
134
|
# Run worker
|
|
102
|
-
|
|
135
|
+
bundle exec postburner --worker default
|
|
103
136
|
```
|
|
104
137
|
|
|
105
138
|
## Table of Contents
|
|
@@ -122,7 +155,33 @@ bin/postburner --config config/postburner.yml --env production
|
|
|
122
155
|
|
|
123
156
|
Beanstalkd is a simple, fast, and reliable queue system. It is a good choice for production environments where you want fast background processing for most jobs, but comprehensive auditing for critical operations.
|
|
124
157
|
|
|
125
|
-
The [protocol](https://github.com/beanstalkd/beanstalkd/blob/master/doc/protocol.txt) reads more like a README than a protocol. Check it out and you will instantly understand how it works.
|
|
158
|
+
The [protocol](https://github.com/beanstalkd/beanstalkd/blob/master/doc/protocol.txt) reads more like a README than a protocol. Check it out and you will instantly understand how it works. Here is a help
|
|
159
|
+
|
|
160
|
+
Here is a picture of the typical job lifecycle:
|
|
161
|
+
|
|
162
|
+
put reserve delete
|
|
163
|
+
-----> [READY] ---------> [RESERVED] --------> *poof*
|
|
164
|
+
|
|
165
|
+
Here is a picture with more possibilities:
|
|
166
|
+
|
|
167
|
+
put with delay release with delay
|
|
168
|
+
----------------> [DELAYED] <------------.
|
|
169
|
+
| |
|
|
170
|
+
| (time passes) |
|
|
171
|
+
| |
|
|
172
|
+
put v reserve | delete
|
|
173
|
+
-----------------> [READY] ---------> [RESERVED] --------> *poof*
|
|
174
|
+
^ ^ | |
|
|
175
|
+
| \ release | |
|
|
176
|
+
| `-------------' |
|
|
177
|
+
| |
|
|
178
|
+
| kick |
|
|
179
|
+
| |
|
|
180
|
+
| bury |
|
|
181
|
+
[BURIED] <---------------'
|
|
182
|
+
|
|
|
183
|
+
| delete
|
|
184
|
+
`--------> *poof*
|
|
126
185
|
|
|
127
186
|
### Binlogs
|
|
128
187
|
|
|
@@ -181,14 +240,14 @@ class ProcessPayment < ApplicationJob
|
|
|
181
240
|
include Postburner::Beanstalkd
|
|
182
241
|
|
|
183
242
|
queue_as :critical
|
|
184
|
-
|
|
243
|
+
priority 0 # Highest priority - processed immediately
|
|
185
244
|
end
|
|
186
245
|
|
|
187
246
|
class SendEmail < ApplicationJob
|
|
188
247
|
include Postburner::Beanstalkd
|
|
189
248
|
|
|
190
249
|
queue_as :mailers
|
|
191
|
-
|
|
250
|
+
priority 1000 # Lower priority - processed after critical jobs
|
|
192
251
|
end
|
|
193
252
|
```
|
|
194
253
|
|
|
@@ -197,7 +256,7 @@ end
|
|
|
197
256
|
```ruby
|
|
198
257
|
class CriticalJob < Postburner::Job
|
|
199
258
|
queue 'critical'
|
|
200
|
-
|
|
259
|
+
priority 0 # Highest priority
|
|
201
260
|
|
|
202
261
|
def perform(args)
|
|
203
262
|
# Critical business logic
|
|
@@ -206,7 +265,7 @@ end
|
|
|
206
265
|
|
|
207
266
|
class BackgroundTask < Postburner::Job
|
|
208
267
|
queue 'default'
|
|
209
|
-
|
|
268
|
+
priority 5000 # Lower priority
|
|
210
269
|
|
|
211
270
|
def perform(args)
|
|
212
271
|
# Non-urgent background work
|
|
@@ -239,7 +298,7 @@ production:
|
|
|
239
298
|
```ruby
|
|
240
299
|
class ProcessOrder < Postburner::Job
|
|
241
300
|
queue 'orders'
|
|
242
|
-
|
|
301
|
+
priority 100 # Default
|
|
243
302
|
|
|
244
303
|
before_enqueue :adjust_priority
|
|
245
304
|
|
|
@@ -252,7 +311,7 @@ class ProcessOrder < Postburner::Job
|
|
|
252
311
|
|
|
253
312
|
def adjust_priority
|
|
254
313
|
if args['urgent']
|
|
255
|
-
self.
|
|
314
|
+
self.priority = 0 # Override to highest priority
|
|
256
315
|
end
|
|
257
316
|
end
|
|
258
317
|
end
|
|
@@ -284,22 +343,22 @@ class ProcessPayment < ApplicationJob
|
|
|
284
343
|
include Postburner::Beanstalkd
|
|
285
344
|
|
|
286
345
|
queue_as :critical
|
|
287
|
-
|
|
288
|
-
|
|
346
|
+
priority 0
|
|
347
|
+
ttr 300 # 5 minutes to complete
|
|
289
348
|
end
|
|
290
349
|
|
|
291
350
|
class QuickEmail < ApplicationJob
|
|
292
351
|
include Postburner::Beanstalkd
|
|
293
352
|
|
|
294
353
|
queue_as :mailers
|
|
295
|
-
|
|
354
|
+
ttr 60 # 1 minute for fast email jobs
|
|
296
355
|
end
|
|
297
356
|
|
|
298
357
|
class LongRunningReport < ApplicationJob
|
|
299
358
|
include Postburner::Beanstalkd
|
|
300
359
|
|
|
301
360
|
queue_as :reports
|
|
302
|
-
|
|
361
|
+
ttr 3600 # 1 hour for complex reports
|
|
303
362
|
end
|
|
304
363
|
```
|
|
305
364
|
|
|
@@ -308,7 +367,7 @@ end
|
|
|
308
367
|
```ruby
|
|
309
368
|
class DataImport < Postburner::Job
|
|
310
369
|
queue 'imports'
|
|
311
|
-
|
|
370
|
+
ttr 1800 # 30 minutes (equivalent to queue_ttr)
|
|
312
371
|
|
|
313
372
|
def perform(args)
|
|
314
373
|
# Long-running import logic
|
|
@@ -329,7 +388,7 @@ class ProcessImport < ApplicationJob
|
|
|
329
388
|
include Postburner::Tracked # Includes Beanstalkd and enables extend!
|
|
330
389
|
|
|
331
390
|
queue_as :imports
|
|
332
|
-
|
|
391
|
+
ttr 300 # 5 minutes initial TTR
|
|
333
392
|
|
|
334
393
|
def perform(file_id)
|
|
335
394
|
file = ImportFile.find(file_id)
|
|
@@ -351,7 +410,7 @@ end
|
|
|
351
410
|
```ruby
|
|
352
411
|
class LargeDataProcessor < Postburner::Job
|
|
353
412
|
queue 'processing'
|
|
354
|
-
|
|
413
|
+
ttr 600 # 10 minutes
|
|
355
414
|
|
|
356
415
|
def perform(args)
|
|
357
416
|
dataset = Dataset.find(args['dataset_id'])
|
|
@@ -370,7 +429,7 @@ end
|
|
|
370
429
|
|
|
371
430
|
- Calls Beanstalkd's `touch` command on the reserved job
|
|
372
431
|
- Resets the TTR countdown to the original TTR value from the current moment
|
|
373
|
-
- Example: Job has `
|
|
432
|
+
- Example: Job has `ttr 300`. After 200 seconds, calling `extend!` gives you another 300 seconds (not just 100)
|
|
374
433
|
- Can be called multiple times during job execution
|
|
375
434
|
- Useful for iterative processing where each iteration is quick but total time is unpredictable
|
|
376
435
|
|
|
@@ -512,8 +571,8 @@ class SendWelcomeEmail < ApplicationJob
|
|
|
512
571
|
include Postburner::Beanstalkd
|
|
513
572
|
|
|
514
573
|
queue_as :mailers
|
|
515
|
-
|
|
516
|
-
|
|
574
|
+
priority 100 # Lower = higher priority (0 is highest)
|
|
575
|
+
ttr 300 # Time-to-run in seconds (5 minutes)
|
|
517
576
|
|
|
518
577
|
def perform(user_id)
|
|
519
578
|
UserMailer.welcome(user_id).deliver_now
|
|
@@ -540,8 +599,8 @@ class ProcessPayment < ApplicationJob
|
|
|
540
599
|
include Postburner::Tracked # ← Opt-in to PostgreSQL tracking (includes Beanstalkd)
|
|
541
600
|
|
|
542
601
|
queue_as :critical
|
|
543
|
-
|
|
544
|
-
|
|
602
|
+
priority 0 # Highest priority (Beanstalkd included automatically)
|
|
603
|
+
ttr 600 # 10 minute timeout
|
|
545
604
|
retry_on StandardError, wait: :exponentially_longer, attempts: 5
|
|
546
605
|
|
|
547
606
|
def perform(payment_id)
|
|
@@ -603,8 +662,8 @@ Direct `Postburner::Job` subclasses are **always tracked**:
|
|
|
603
662
|
```ruby
|
|
604
663
|
class RunDonation < Postburner::Job
|
|
605
664
|
queue 'critical'
|
|
606
|
-
|
|
607
|
-
|
|
665
|
+
priority 0
|
|
666
|
+
max_retries 0
|
|
608
667
|
|
|
609
668
|
def perform(args)
|
|
610
669
|
donation = Donation.find(args['donation_id'])
|
|
@@ -639,15 +698,15 @@ job.queue!
|
|
|
639
698
|
|
|
640
699
|
# Set dynamically after creation
|
|
641
700
|
job = RunDonation.create!(args: { 'donation_id' => 456 })
|
|
642
|
-
job.
|
|
643
|
-
job.
|
|
701
|
+
job.priority = 2000
|
|
702
|
+
job.ttr = 300
|
|
644
703
|
job.queue!
|
|
645
704
|
|
|
646
705
|
# Use in before_enqueue callback for conditional behavior
|
|
647
706
|
class ProcessOrder < Postburner::Job
|
|
648
707
|
queue 'orders'
|
|
649
|
-
|
|
650
|
-
|
|
708
|
+
priority 100 # Default priority
|
|
709
|
+
ttr 120 # Default TTR
|
|
651
710
|
|
|
652
711
|
before_enqueue :set_priority_based_on_urgency
|
|
653
712
|
|
|
@@ -660,11 +719,11 @@ class ProcessOrder < Postburner::Job
|
|
|
660
719
|
|
|
661
720
|
def set_priority_based_on_urgency
|
|
662
721
|
if args['express_shipping']
|
|
663
|
-
self.
|
|
664
|
-
self.
|
|
722
|
+
self.priority = 0 # High priority for express orders
|
|
723
|
+
self.ttr = 600 # Allow 10 minutes to complete
|
|
665
724
|
else
|
|
666
|
-
self.
|
|
667
|
-
self.
|
|
725
|
+
self.priority = 1000 # Low priority for standard orders
|
|
726
|
+
self.ttr = 120 # Standard 2 minute timeout
|
|
668
727
|
end
|
|
669
728
|
end
|
|
670
729
|
end
|
|
@@ -686,24 +745,25 @@ Postburner uses named worker configurations to support different deployment patt
|
|
|
686
745
|
Configure multiple named workers with different concurrency profiles:
|
|
687
746
|
|
|
688
747
|
```yaml
|
|
689
|
-
production:
|
|
748
|
+
production: # <- environment config, i.e. defaults
|
|
690
749
|
beanstalk_url: <%= ENV['BEANSTALK_URL'] %>
|
|
750
|
+
default_forks: 2
|
|
751
|
+
default_threads: 10
|
|
752
|
+
default_gc_limit: 5000
|
|
691
753
|
|
|
692
|
-
workers:
|
|
754
|
+
workers: # <- worker config, i.e. overrides
|
|
693
755
|
# Heavy, memory-intensive jobs - more processes, fewer threads
|
|
694
756
|
imports:
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
757
|
+
forks: 4 # Overrides default_forks
|
|
758
|
+
threads: 1 # Overrides default_threads
|
|
759
|
+
gc_limit: 500 # Overrides default_gc_limit
|
|
698
760
|
queues:
|
|
699
761
|
- imports
|
|
700
762
|
- data_processing
|
|
701
763
|
|
|
702
764
|
# General jobs - fewer processes, many threads
|
|
703
765
|
general:
|
|
704
|
-
|
|
705
|
-
default_threads: 100
|
|
706
|
-
default_gc_limit: 5000
|
|
766
|
+
threads: 100 # Overrides default_threads (forks uses default_forks=2)
|
|
707
767
|
queues:
|
|
708
768
|
- default
|
|
709
769
|
- mailers
|
|
@@ -722,12 +782,12 @@ This gives you a natural progression from simple single-threaded development to
|
|
|
722
782
|
|
|
723
783
|
**Development (single worker, single-threaded):**
|
|
724
784
|
```yaml
|
|
725
|
-
development:
|
|
785
|
+
development: # <- environment config
|
|
726
786
|
beanstalk_url: beanstalk://localhost:11300
|
|
727
787
|
|
|
728
|
-
workers:
|
|
788
|
+
workers: # <- worker config
|
|
729
789
|
default:
|
|
730
|
-
#
|
|
790
|
+
# Uses env defaults: forks=0, threads=1, gc_limit=nil
|
|
731
791
|
queues:
|
|
732
792
|
- default
|
|
733
793
|
- mailers
|
|
@@ -735,13 +795,14 @@ development:
|
|
|
735
795
|
|
|
736
796
|
**Staging (single worker, multi-threaded):**
|
|
737
797
|
```yaml
|
|
738
|
-
staging:
|
|
798
|
+
staging: # <- environment config
|
|
739
799
|
beanstalk_url: beanstalk://localhost:11300
|
|
800
|
+
default_threads: 10
|
|
801
|
+
default_gc_limit: 5000
|
|
740
802
|
|
|
741
|
-
workers:
|
|
803
|
+
workers: # <- worker config
|
|
742
804
|
default:
|
|
743
|
-
|
|
744
|
-
default_gc_limit: 5000
|
|
805
|
+
# Uses env defaults: default_threads=10, default_gc_limit=5000
|
|
745
806
|
queues:
|
|
746
807
|
- critical
|
|
747
808
|
- default
|
|
@@ -750,22 +811,25 @@ staging:
|
|
|
750
811
|
|
|
751
812
|
**Production (multiple workers with different profiles):**
|
|
752
813
|
```yaml
|
|
753
|
-
production:
|
|
814
|
+
production: # <- environment config, i.e. defaults
|
|
754
815
|
beanstalk_url: <%= ENV['BEANSTALK_URL'] %>
|
|
816
|
+
default_forks: 2
|
|
817
|
+
default_threads: 10
|
|
818
|
+
default_gc_limit: 5000
|
|
755
819
|
|
|
756
|
-
workers:
|
|
820
|
+
workers: # <- worker config, i.e. overrides
|
|
757
821
|
imports:
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
822
|
+
forks: 4 # Overrides default_forks (4 processes)
|
|
823
|
+
threads: 1 # Overrides default_threads (1 thread per process = 4 concurrent jobs)
|
|
824
|
+
gc_limit: 500 # Overrides default_gc_limit
|
|
761
825
|
queues:
|
|
762
826
|
- imports
|
|
763
827
|
- data_processing
|
|
764
828
|
|
|
765
829
|
general:
|
|
766
|
-
default_forks
|
|
767
|
-
|
|
768
|
-
default_gc_limit
|
|
830
|
+
# forks uses default_forks=2 (2 processes)
|
|
831
|
+
threads: 100 # Overrides default_threads (100 threads per process = 200 concurrent jobs)
|
|
832
|
+
# gc_limit uses default_gc_limit=5000
|
|
769
833
|
queues:
|
|
770
834
|
- default
|
|
771
835
|
- mailers
|
|
@@ -872,7 +936,7 @@ Parent Process
|
|
|
872
936
|
|
|
873
937
|
### GC Limits
|
|
874
938
|
|
|
875
|
-
Set `default_gc_limit` per worker to automatically restart after processing N jobs.
|
|
939
|
+
Set `default_gc_limit` at environment level or `gc_limit` per worker to automatically restart after processing N jobs.
|
|
876
940
|
|
|
877
941
|
- Worker processes N jobs
|
|
878
942
|
- Worker exits with code 99
|
|
@@ -880,20 +944,23 @@ Set `default_gc_limit` per worker to automatically restart after processing N jo
|
|
|
880
944
|
- In multi-process mode (forks: 1+): parent process automatically restarts just that fork
|
|
881
945
|
|
|
882
946
|
```yaml
|
|
883
|
-
production:
|
|
884
|
-
|
|
947
|
+
production: # <- environment config
|
|
948
|
+
default_forks: 2
|
|
949
|
+
default_threads: 10
|
|
950
|
+
default_gc_limit: 5000
|
|
951
|
+
|
|
952
|
+
workers: # <- worker config
|
|
885
953
|
imports:
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
954
|
+
forks: 4 # Overrides default_forks
|
|
955
|
+
threads: 1 # Overrides default_threads
|
|
956
|
+
gc_limit: 500 # Overrides default_gc_limit (restart after 500 jobs, memory-intensive)
|
|
889
957
|
queues:
|
|
890
958
|
- imports
|
|
891
959
|
- data_processing
|
|
892
960
|
|
|
893
961
|
general:
|
|
894
|
-
default_forks
|
|
895
|
-
|
|
896
|
-
default_gc_limit: 5000 # Restart after 5000 jobs
|
|
962
|
+
# Uses default_forks=2, default_threads=100, default_gc_limit=5000 (restart after 5000 jobs)
|
|
963
|
+
threads: 100 # Overrides default_threads
|
|
897
964
|
queues:
|
|
898
965
|
- default
|
|
899
966
|
- mailers
|
|
@@ -913,48 +980,64 @@ production:
|
|
|
913
980
|
default: &default
|
|
914
981
|
beanstalk_url: <%= ENV['BEANSTALK_URL'] || 'beanstalk://localhost:11300' %>
|
|
915
982
|
|
|
916
|
-
development:
|
|
983
|
+
development: # <- environment config
|
|
917
984
|
<<: *default
|
|
918
|
-
#
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
985
|
+
# Env defaults: forks=0, threads=1, gc_limit=nil
|
|
986
|
+
|
|
987
|
+
workers: # <- worker config
|
|
988
|
+
default:
|
|
989
|
+
queues:
|
|
990
|
+
- default
|
|
991
|
+
- mailers
|
|
922
992
|
|
|
923
|
-
test:
|
|
993
|
+
test: # <- environment config
|
|
924
994
|
<<: *default
|
|
925
|
-
#
|
|
926
|
-
queues:
|
|
927
|
-
default: {}
|
|
995
|
+
# Env defaults: forks=0, threads=1, gc_limit=nil
|
|
928
996
|
|
|
929
|
-
|
|
997
|
+
workers: # <- worker config
|
|
998
|
+
default:
|
|
999
|
+
queues:
|
|
1000
|
+
- default
|
|
1001
|
+
|
|
1002
|
+
staging: # <- environment config
|
|
930
1003
|
<<: *default
|
|
931
1004
|
default_threads: 10 # Multi-threaded, single process
|
|
932
1005
|
default_gc_limit: 5000
|
|
933
|
-
queues:
|
|
934
|
-
default: {}
|
|
935
|
-
mailers: {}
|
|
936
1006
|
|
|
937
|
-
|
|
1007
|
+
workers: # <- worker config
|
|
1008
|
+
default:
|
|
1009
|
+
# Uses env defaults: default_threads=10, default_gc_limit=5000
|
|
1010
|
+
queues:
|
|
1011
|
+
- default
|
|
1012
|
+
- mailers
|
|
1013
|
+
|
|
1014
|
+
production: # <- environment config, i.e. defaults
|
|
938
1015
|
<<: *default
|
|
939
|
-
default_forks:
|
|
940
|
-
default_threads: 10 #
|
|
941
|
-
default_gc_limit: 5000
|
|
1016
|
+
default_forks: 2 # Default for workers
|
|
1017
|
+
default_threads: 10 # Default for workers
|
|
1018
|
+
default_gc_limit: 5000 # Default for workers
|
|
942
1019
|
|
|
943
|
-
|
|
1020
|
+
workers: # <- worker config, i.e. overrides
|
|
944
1021
|
critical:
|
|
945
|
-
forks: 1
|
|
946
|
-
threads: 1 # 1 concurrent job
|
|
947
|
-
gc_limit: 100
|
|
1022
|
+
forks: 1 # Overrides default_forks
|
|
1023
|
+
threads: 1 # Overrides default_threads (1 concurrent job)
|
|
1024
|
+
gc_limit: 100 # Overrides default_gc_limit
|
|
1025
|
+
queues:
|
|
1026
|
+
- critical
|
|
948
1027
|
|
|
949
1028
|
default:
|
|
950
|
-
forks: 4
|
|
951
|
-
threads: 10 # 40 total concurrent jobs
|
|
952
|
-
gc_limit: 1000
|
|
1029
|
+
forks: 4 # Overrides default_forks
|
|
1030
|
+
threads: 10 # Overrides default_threads (40 total concurrent jobs: 4 × 10)
|
|
1031
|
+
gc_limit: 1000 # Overrides default_gc_limit
|
|
1032
|
+
queues:
|
|
1033
|
+
- default
|
|
953
1034
|
|
|
954
1035
|
mailers:
|
|
955
|
-
forks
|
|
956
|
-
threads: 5 # 10 total email senders
|
|
957
|
-
gc_limit: 500
|
|
1036
|
+
# forks uses default_forks=2
|
|
1037
|
+
threads: 5 # Overrides default_threads (10 total email senders: 2 × 5)
|
|
1038
|
+
gc_limit: 500 # Overrides default_gc_limit
|
|
1039
|
+
queues:
|
|
1040
|
+
- mailers
|
|
958
1041
|
```
|
|
959
1042
|
|
|
960
1043
|
### Queue Configuration Methods
|
|
@@ -964,10 +1047,10 @@ For `Postburner::Job` subclasses (and backwards compatibility):
|
|
|
964
1047
|
```ruby
|
|
965
1048
|
class CriticalJob < Postburner::Job
|
|
966
1049
|
queue 'critical' # Beanstalkd tube name
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
1050
|
+
priority 0 # Lower = higher priority (0 is highest)
|
|
1051
|
+
ttr 300 # TTR (time-to-run) in seconds
|
|
1052
|
+
max_retries 3 # Max retry attempts
|
|
1053
|
+
retry_delay 5 # Fixed delay: 5 seconds between retries
|
|
971
1054
|
|
|
972
1055
|
def perform(args)
|
|
973
1056
|
# ...
|
|
@@ -980,8 +1063,8 @@ end
|
|
|
980
1063
|
```ruby
|
|
981
1064
|
class BackgroundTask < Postburner::Job
|
|
982
1065
|
queue 'default'
|
|
983
|
-
|
|
984
|
-
|
|
1066
|
+
max_retries 5
|
|
1067
|
+
retry_delay ->(retries) { 2 ** retries } # 2s, 4s, 8s, 16s, 32s
|
|
985
1068
|
|
|
986
1069
|
def perform(args)
|
|
987
1070
|
# ...
|
|
@@ -1341,6 +1424,10 @@ Key changes in v1.0:
|
|
|
1341
1424
|
|
|
1342
1425
|
Submit a pull request. Follow project conventions. Be nice.
|
|
1343
1426
|
|
|
1427
|
+
There is a CLAUDE.md file for guidance when using Claude Code. Please use it or contribute to it. Do NOT reference AI tools in commits or code. Do not co-author with AI tools. Pull requests will be rejected if they violate these rules.
|
|
1428
|
+
|
|
1429
|
+
We encourage AI tools, but do not vibe, as the code must look like it was written by a human. Code that contains AI agent idioms will be rejected. Code that doesn't follow the project conventions will be rejected.
|
|
1430
|
+
|
|
1344
1431
|
## License
|
|
1345
1432
|
|
|
1346
1433
|
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|