postburner 1.0.0.pre.13 → 1.0.0.pre.14
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 +152 -81
- data/app/concerns/postburner/insertion.rb +17 -1
- data/app/models/postburner/schedule.rb +50 -0
- data/app/models/postburner/schedule_execution.rb +19 -0
- data/bin/postburner +13 -5
- data/lib/generators/postburner/install/templates/config/postburner.yml +24 -139
- data/lib/postburner/active_job/adapter.rb +51 -1
- data/lib/postburner/instrumentation.rb +196 -0
- data/lib/postburner/scheduler.rb +74 -20
- data/lib/postburner/strategies/{nice_queue.rb → default_queue.rb} +10 -10
- data/lib/postburner/strategies/{test_queue.rb → inline_test_queue.rb} +10 -7
- data/lib/postburner/strategies/{queue.rb → strict_queue.rb} +12 -12
- data/lib/postburner/strategies/{immediate_test_queue.rb → time_travel_test_queue.rb} +15 -12
- data/lib/postburner/test_helpers.rb +133 -0
- data/lib/postburner/version.rb +1 -1
- data/lib/postburner/worker.rb +26 -12
- data/lib/postburner.rb +51 -49
- metadata +7 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 71c6a81826b32021b0f0083c1771b27423e1b25198d7c00669cbab1150c431e7
|
|
4
|
+
data.tar.gz: 26403dba984c15f4bad94d81f1f5833d6a6bb16c0bb216a236f6bcaf07c0d019
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: bc088b5d6e5b36b514562635ee3ed75955dfe809efe981e3ddbdc47c5f5387715233b7eb0eec8b4e78f97cf715202beabb7f8b90df553c605eec058eee462a9c
|
|
7
|
+
data.tar.gz: 40dbfc6f0979226d5c67780ffe31c73700a6a7b7faf97bf8e7fd127a2c889e708db91835bc9389032191ae2fae6460f3cc1b21f28ee17a6a3f00dbc84c31fbea
|
data/README.md
CHANGED
|
@@ -110,7 +110,6 @@ bundle exec rake postburner:work WORKER=default
|
|
|
110
110
|
- [Why Beanstalkd?](#why-beanstalkd)
|
|
111
111
|
- [Beanstalkd Integration](#beanstalkd-integration)
|
|
112
112
|
- [Installation](#installation)
|
|
113
|
-
- [Deployment](#deployment)
|
|
114
113
|
- [Web UI - v2 Coming Soon](#web-ui)
|
|
115
114
|
|
|
116
115
|
## Why
|
|
@@ -787,36 +786,42 @@ Postburner uses different strategies to control job execution. These affect `Pos
|
|
|
787
786
|
|
|
788
787
|
| Strategy | When to Use | Behavior | Requires Beanstalkd |
|
|
789
788
|
|----------|-------------|----------|---------------------|
|
|
790
|
-
| **
|
|
791
|
-
| **
|
|
792
|
-
| **
|
|
793
|
-
| **
|
|
794
|
-
| **
|
|
789
|
+
| **DefaultQueue** | Production | Async, gracefully requeues premature jobs | Yes |
|
|
790
|
+
| **StrictQueue** | Production | Async via Beanstalkd, raises error on premature execution | Yes |
|
|
791
|
+
| **NullQueue** | Test (usually) | Jobs created but not inserted into Beanstalkd, manual execution | No |
|
|
792
|
+
| **InlineTestQueue** | Test | Inline execution (error raised for delayed jobs) | No |
|
|
793
|
+
| **TimeTravelTestQueue** | Test | Inline execution, (auto time-travels for delayed jobs) | No |
|
|
795
794
|
|
|
796
795
|
```ruby
|
|
797
796
|
# Switch strategies
|
|
798
|
-
Postburner.
|
|
799
|
-
Postburner.
|
|
800
|
-
Postburner.
|
|
801
|
-
Postburner.
|
|
802
|
-
Postburner.
|
|
797
|
+
Postburner.default_strategy! # Default production (DefaultQueue)
|
|
798
|
+
Postburner.strict_strategy! # Strict production (StrictQueue)
|
|
799
|
+
Postburner.null_strategy! # Deferred, or manual execution
|
|
800
|
+
Postburner.inline_test_strategy! # Testing (InlineTestQueue)
|
|
801
|
+
Postburner.time_travel_test_strategy! # Testing inline but also with time travel
|
|
803
802
|
```
|
|
804
803
|
|
|
805
|
-
|
|
804
|
+
### Adding a Queue Strategy
|
|
806
805
|
|
|
807
|
-
|
|
806
|
+
There are 4 hook methods that are used with inheritance:
|
|
807
|
+
- `insert` - Inserts the job into the queue
|
|
808
|
+
- `handle_perform!` - Handles the job being performed
|
|
809
|
+
- `handle_premature_perform` - Handles jobs executed before their scheduled run_at time
|
|
810
|
+
- `testing` - Returns true if the strategy is for testing
|
|
808
811
|
|
|
809
|
-
|
|
812
|
+
## Testing
|
|
810
813
|
|
|
811
814
|
### Automatic Test Mode
|
|
812
815
|
|
|
813
|
-
In Rails test environments, Postburner automatically uses inline execution:
|
|
816
|
+
In Rails test environments, Postburner automatically uses inline execution via the `InlineTestQueue` strategy:
|
|
814
817
|
|
|
815
818
|
```ruby
|
|
816
819
|
# test/test_helper.rb - automatic!
|
|
817
820
|
Postburner.testing? # => true in tests
|
|
818
821
|
```
|
|
819
822
|
|
|
823
|
+
Postburner provides test-friendly execution modes that don't require Beanstalkd.
|
|
824
|
+
|
|
820
825
|
### Testing Default Jobs (ActiveJob)
|
|
821
826
|
|
|
822
827
|
Use standard ActiveJob test helpers:
|
|
@@ -850,26 +855,47 @@ test "tracked job logs execution" do
|
|
|
850
855
|
end
|
|
851
856
|
```
|
|
852
857
|
|
|
853
|
-
###
|
|
858
|
+
### Switching Queue Strategies
|
|
859
|
+
|
|
860
|
+
For tests requiring specific queue behaviors, use `switch_queue_strategy!` and `restore_queue_strategy!`:
|
|
854
861
|
|
|
855
862
|
```ruby
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
863
|
+
class ScheduleTest < ActiveSupport::TestCase
|
|
864
|
+
def setup
|
|
865
|
+
switch_queue_strategy! Postburner::TimeTravelTestQueue
|
|
866
|
+
end
|
|
867
|
+
|
|
868
|
+
def teardown
|
|
869
|
+
restore_queue_strategy!
|
|
870
|
+
end
|
|
859
871
|
|
|
860
|
-
|
|
872
|
+
test "scheduled job executes" do
|
|
873
|
+
job = MyJob.create!(args: {})
|
|
874
|
+
job.queue!(delay: 1.hour)
|
|
875
|
+
assert job.reload.processed_at # Auto time-travels
|
|
876
|
+
end
|
|
861
877
|
end
|
|
878
|
+
```
|
|
862
879
|
|
|
863
|
-
|
|
864
|
-
job = ProcessPayment.create!(args: { 'payment_id' => 123 })
|
|
880
|
+
**Block form for isolated tests:**
|
|
865
881
|
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
882
|
+
```ruby
|
|
883
|
+
test "specific strategy for one test" do
|
|
884
|
+
use_queue_strategy Postburner::NullQueue do
|
|
885
|
+
job = MyJob.create!(args: {})
|
|
886
|
+
job.queue!
|
|
887
|
+
assert_nil job.bkid # Not queued to Beanstalkd
|
|
869
888
|
end
|
|
870
889
|
end
|
|
871
890
|
```
|
|
872
891
|
|
|
892
|
+
**Available strategies:**
|
|
893
|
+
- `Postburner::InlineTestQueue` - Default test mode, raises on delayed jobs
|
|
894
|
+
- `Postburner::TimeTravelTestQueue` - Auto time-travel for delayed jobs
|
|
895
|
+
- `Postburner::NullQueue` - Create jobs without queueing
|
|
896
|
+
- `Postburner::StrictQueue` - Production mode with error on premature execution
|
|
897
|
+
- `Postburner::DefaultQueue` - Production mode with graceful requeue
|
|
898
|
+
|
|
873
899
|
## Workers
|
|
874
900
|
|
|
875
901
|
Postburner uses named worker configurations to support different deployment patterns. Each worker can have different fork/thread settings and process different queues, enabling flexible production deployments.
|
|
@@ -989,6 +1015,8 @@ bin/postburner --worker general # Run the 'general' worker
|
|
|
989
1015
|
bin/postburner --worker general --queues default,mailers # Only process specific queues
|
|
990
1016
|
```
|
|
991
1017
|
|
|
1018
|
+
**Note:** Prefer defining separate workers in `config/postburner.yml` rather than using `--queues` overrides. Named workers make your deployment configuration explicit and version-controlled. Use `--queues` only for debugging or temporary overrides.
|
|
1019
|
+
|
|
992
1020
|
**Rake task:**
|
|
993
1021
|
```bash
|
|
994
1022
|
bundle exec rake postburner:work # Auto-select worker
|
|
@@ -1240,6 +1268,15 @@ production: # <- environment config, i.e. defaults
|
|
|
1240
1268
|
- mailers
|
|
1241
1269
|
```
|
|
1242
1270
|
|
|
1271
|
+
**Start workers with:**
|
|
1272
|
+
|
|
1273
|
+
```bash
|
|
1274
|
+
bin/postburner # Auto-select single worker
|
|
1275
|
+
bin/postburner --worker default # Specify worker
|
|
1276
|
+
rake postburner:work # Rake task (auto-select)
|
|
1277
|
+
rake postburner:work WORKER=default
|
|
1278
|
+
```
|
|
1279
|
+
|
|
1243
1280
|
### Queue Names
|
|
1244
1281
|
|
|
1245
1282
|
Postburner automatically prefixes all queue names with `postburner.{env}.` to create Beanstalkd tube names. This namespacing prevents collisions when multiple applications share the same Beanstalkd server.
|
|
@@ -1372,16 +1409,86 @@ end
|
|
|
1372
1409
|
|
|
1373
1410
|
## Instrumentation
|
|
1374
1411
|
|
|
1375
|
-
Postburner emits ActiveSupport::Notifications events following
|
|
1412
|
+
Postburner emits ActiveSupport::Notifications events following Rails conventions. Use these for monitoring, logging, or alerting.
|
|
1413
|
+
|
|
1414
|
+
### Job Events
|
|
1415
|
+
|
|
1416
|
+
| Event | When | Payload Keys |
|
|
1417
|
+
|-------|------|--------------|
|
|
1418
|
+
| `perform_start.job.postburner` | Before job execution begins | `:job`, `:beanstalk_job_id` |
|
|
1419
|
+
| `perform.job.postburner` | Around job execution (includes duration) | `:job`, `:beanstalk_job_id` |
|
|
1420
|
+
| `retry.job.postburner` | When job is retried after error | `:job`, `:beanstalk_job_id`, `:error`, `:wait`, `:attempt` |
|
|
1421
|
+
| `retry_stopped.job.postburner` | When tracked job exhausts retries | `:job`, `:beanstalk_job_id`, `:error` |
|
|
1422
|
+
| `discard.job.postburner` | When default job exhausts retries | `:job`, `:beanstalk_job_id`, `:error` |
|
|
1423
|
+
| `enqueue.job.postburner` | When job is enqueued for immediate execution | `:job` |
|
|
1424
|
+
| `enqueue_at.job.postburner` | When job is enqueued with delay | `:job`, `:scheduled_at` |
|
|
1425
|
+
|
|
1426
|
+
**Job Payload Structure:**
|
|
1427
|
+
|
|
1428
|
+
```ruby
|
|
1429
|
+
{
|
|
1430
|
+
class: "ProcessPayment", # Job class name
|
|
1431
|
+
id: 123, # Postburner job ID (tracked jobs only)
|
|
1432
|
+
job_id: "abc-123", # ActiveJob UUID
|
|
1433
|
+
arguments: { payment_id: 456 }, # Job arguments
|
|
1434
|
+
queue_name: "critical", # Queue name
|
|
1435
|
+
beanstalk_job_id: 789, # Beanstalkd job ID
|
|
1436
|
+
tracked: true # Whether job is tracked in PostgreSQL
|
|
1437
|
+
}
|
|
1438
|
+
```
|
|
1376
1439
|
|
|
1377
|
-
###
|
|
1440
|
+
### Schedule Events
|
|
1378
1441
|
|
|
1379
1442
|
| Event | When | Payload Keys |
|
|
1380
1443
|
|-------|------|--------------|
|
|
1381
|
-
| `
|
|
1382
|
-
| `
|
|
1383
|
-
| `
|
|
1384
|
-
|
|
1444
|
+
| `create.schedule.postburner` | When schedule is created | `:schedule` |
|
|
1445
|
+
| `update.schedule.postburner` | When schedule is updated | `:schedule`, `:changes` |
|
|
1446
|
+
| `audit.schedule.postburner` | When scheduler audits a schedule | `:schedule` |
|
|
1447
|
+
|
|
1448
|
+
**Schedule Payload Structure:**
|
|
1449
|
+
|
|
1450
|
+
```ruby
|
|
1451
|
+
{
|
|
1452
|
+
id: 1,
|
|
1453
|
+
name: "daily_cleanup",
|
|
1454
|
+
job_class: "CleanupJob",
|
|
1455
|
+
enabled: true,
|
|
1456
|
+
cron: nil,
|
|
1457
|
+
anchor: "2025-01-01T09:00:00Z",
|
|
1458
|
+
interval: 1,
|
|
1459
|
+
interval_unit: "days"
|
|
1460
|
+
}
|
|
1461
|
+
```
|
|
1462
|
+
|
|
1463
|
+
### Schedule Execution Events
|
|
1464
|
+
|
|
1465
|
+
| Event | When | Payload Keys |
|
|
1466
|
+
|-------|------|--------------|
|
|
1467
|
+
| `create.schedule_execution.postburner` | When execution is created | `:schedule`, `:execution` |
|
|
1468
|
+
| `enqueue.schedule_execution.postburner` | When execution is enqueued to Beanstalkd | `:schedule`, `:execution`, `:beanstalk_job_id` |
|
|
1469
|
+
| `skip.schedule_execution.postburner` | When execution is skipped | `:schedule`, `:execution` |
|
|
1470
|
+
|
|
1471
|
+
**Execution Payload Structure:**
|
|
1472
|
+
|
|
1473
|
+
```ruby
|
|
1474
|
+
{
|
|
1475
|
+
id: 42,
|
|
1476
|
+
schedule_id: 1,
|
|
1477
|
+
status: "scheduled",
|
|
1478
|
+
run_at: "2025-01-15T09:00:00Z",
|
|
1479
|
+
next_run_at: "2025-01-16T09:00:00Z",
|
|
1480
|
+
enqueued_at: "2025-01-14T10:00:00Z",
|
|
1481
|
+
beanstalk_job_id: 789,
|
|
1482
|
+
job_id: 123
|
|
1483
|
+
}
|
|
1484
|
+
```
|
|
1485
|
+
|
|
1486
|
+
### Scheduler Events
|
|
1487
|
+
|
|
1488
|
+
| Event | When | Payload Keys |
|
|
1489
|
+
|-------|------|--------------|
|
|
1490
|
+
| `perform_start.scheduler.postburner` | Before scheduler watchdog runs | `:interval` |
|
|
1491
|
+
| `perform.scheduler.postburner` | Around scheduler watchdog (includes summary) | `:interval`, `:lock_acquired`, `:schedules_processed`, `:schedules_failed`, `:executions_created`, `:orphans_enqueued` |
|
|
1385
1492
|
|
|
1386
1493
|
### Subscribing to Events
|
|
1387
1494
|
|
|
@@ -1389,32 +1496,39 @@ Postburner emits ActiveSupport::Notifications events following ActiveJob convent
|
|
|
1389
1496
|
# config/initializers/postburner_instrumentation.rb
|
|
1390
1497
|
|
|
1391
1498
|
# Log all job executions
|
|
1392
|
-
ActiveSupport::Notifications.subscribe('perform.postburner') do |name, start, finish, id, payload|
|
|
1499
|
+
ActiveSupport::Notifications.subscribe('perform.job.postburner') do |name, start, finish, id, payload|
|
|
1393
1500
|
duration = (finish - start) * 1000
|
|
1394
|
-
Rails.logger.info "[Postburner] #{payload[:
|
|
1501
|
+
Rails.logger.info "[Postburner] #{payload[:job][:class]} completed in #{duration.round(2)}ms"
|
|
1395
1502
|
end
|
|
1396
1503
|
|
|
1397
1504
|
# Alert on discarded jobs
|
|
1398
|
-
ActiveSupport::Notifications.subscribe('discard.postburner') do |*args|
|
|
1505
|
+
ActiveSupport::Notifications.subscribe('discard.job.postburner') do |*args|
|
|
1399
1506
|
payload = args.last
|
|
1400
1507
|
Alerting.notify(
|
|
1401
1508
|
"Job discarded after max retries",
|
|
1402
|
-
job_class: payload[:
|
|
1509
|
+
job_class: payload[:job][:class],
|
|
1403
1510
|
error: payload[:error].message
|
|
1404
1511
|
)
|
|
1405
1512
|
end
|
|
1406
1513
|
|
|
1407
1514
|
# Track retry metrics
|
|
1408
|
-
ActiveSupport::Notifications.subscribe('retry.postburner') do |*args|
|
|
1515
|
+
ActiveSupport::Notifications.subscribe('retry.job.postburner') do |*args|
|
|
1409
1516
|
payload = args.last
|
|
1410
1517
|
StatsD.increment('postburner.retry', tags: [
|
|
1411
|
-
"job:#{payload[:
|
|
1518
|
+
"job:#{payload[:job][:class]}",
|
|
1412
1519
|
"attempt:#{payload[:attempt]}"
|
|
1413
1520
|
])
|
|
1414
1521
|
end
|
|
1522
|
+
|
|
1523
|
+
# Monitor scheduler performance
|
|
1524
|
+
ActiveSupport::Notifications.subscribe('perform.scheduler.postburner') do |name, start, finish, id, payload|
|
|
1525
|
+
duration = (finish - start) * 1000
|
|
1526
|
+
Rails.logger.info "[Scheduler] Processed #{payload[:schedules_processed]} schedules, " \
|
|
1527
|
+
"created #{payload[:executions_created]} executions in #{duration.round(2)}ms"
|
|
1528
|
+
end
|
|
1415
1529
|
```
|
|
1416
1530
|
|
|
1417
|
-
**Note:** These events
|
|
1531
|
+
**Note:** These events complement (don't replace) ActiveJob's built-in instrumentation events like `enqueue.active_job` and `perform.active_job`.
|
|
1418
1532
|
|
|
1419
1533
|
## Why Beanstalkd?
|
|
1420
1534
|
|
|
@@ -1960,49 +2074,6 @@ cp config/postburner.yml.example config/postburner.yml
|
|
|
1960
2074
|
|
|
1961
2075
|
Edit `config/postburner.yml` for your environment (see [Configuration](#configuration)).
|
|
1962
2076
|
|
|
1963
|
-
## Deployment
|
|
1964
|
-
|
|
1965
|
-
Some recipies that might be useful or instructive:
|
|
1966
|
-
|
|
1967
|
-
### Docker
|
|
1968
|
-
|
|
1969
|
-
```dockerfile
|
|
1970
|
-
# Dockerfile.worker
|
|
1971
|
-
FROM ruby:3.3
|
|
1972
|
-
|
|
1973
|
-
WORKDIR /app
|
|
1974
|
-
COPY . .
|
|
1975
|
-
RUN bundle install
|
|
1976
|
-
|
|
1977
|
-
CMD ["bundle", "exec", "postburner", "--config", "config/postburner.yml", "--env", "production"]
|
|
1978
|
-
```
|
|
1979
|
-
|
|
1980
|
-
```yaml
|
|
1981
|
-
# docker-compose.yml
|
|
1982
|
-
services:
|
|
1983
|
-
beanstalkd:
|
|
1984
|
-
image: schickling/beanstalkd
|
|
1985
|
-
command: ["-l", "0.0.0.0", "-p", "11300", "-b", "/var/lib/beanstalkd"]
|
|
1986
|
-
ports:
|
|
1987
|
-
- "11300:11300"
|
|
1988
|
-
volumes:
|
|
1989
|
-
- beanstalkd_data:/var/lib/beanstalkd
|
|
1990
|
-
|
|
1991
|
-
worker:
|
|
1992
|
-
build:
|
|
1993
|
-
context: .
|
|
1994
|
-
dockerfile: Dockerfile.worker
|
|
1995
|
-
depends_on:
|
|
1996
|
-
- beanstalkd
|
|
1997
|
-
- postgres
|
|
1998
|
-
environment:
|
|
1999
|
-
BEANSTALK_URL: beanstalk://beanstalkd:11300
|
|
2000
|
-
DATABASE_URL: postgres://postgres@postgres/myapp_production
|
|
2001
|
-
|
|
2002
|
-
volumes:
|
|
2003
|
-
beanstalkd_data:
|
|
2004
|
-
```
|
|
2005
|
-
|
|
2006
2077
|
## Migration from v0.x
|
|
2007
2078
|
|
|
2008
2079
|
Key changes in v1.0:
|
|
@@ -151,6 +151,10 @@ module Postburner
|
|
|
151
151
|
# queueing (Beanstalkd in production, inline execution in test mode).
|
|
152
152
|
# Updates bkid if the strategy returns a Beanstalkd job ID.
|
|
153
153
|
#
|
|
154
|
+
# Instruments with ActiveSupport::Notifications:
|
|
155
|
+
# - enqueue.job.postburner: When job is queued immediately
|
|
156
|
+
# - enqueue_at.job.postburner: When job is queued with delay/at
|
|
157
|
+
#
|
|
154
158
|
# @param options [Hash] Queue options (delay, pri, ttr, etc.)
|
|
155
159
|
#
|
|
156
160
|
# @return [Hash, nil] Queue strategy response
|
|
@@ -159,7 +163,6 @@ module Postburner
|
|
|
159
163
|
#
|
|
160
164
|
def insert!(options={})
|
|
161
165
|
response = Postburner.queue_strategy.insert(self, options)
|
|
162
|
-
#debugger
|
|
163
166
|
|
|
164
167
|
# Response must be a hash with an :id key (value can be nil)
|
|
165
168
|
unless response.is_a?(Hash) && response.key?(:id)
|
|
@@ -168,6 +171,19 @@ module Postburner
|
|
|
168
171
|
|
|
169
172
|
persist_metadata!(bkid: response[:id])
|
|
170
173
|
|
|
174
|
+
# Instrument enqueue event
|
|
175
|
+
job_payload = Postburner::Instrumentation.job_payload_from_model(self, beanstalk_job_id: response[:id])
|
|
176
|
+
if self.run_at.present? && self.run_at > Time.current
|
|
177
|
+
ActiveSupport::Notifications.instrument('enqueue_at.job.postburner', {
|
|
178
|
+
job: job_payload,
|
|
179
|
+
scheduled_at: self.run_at
|
|
180
|
+
})
|
|
181
|
+
else
|
|
182
|
+
ActiveSupport::Notifications.instrument('enqueue.job.postburner', {
|
|
183
|
+
job: job_payload
|
|
184
|
+
})
|
|
185
|
+
end
|
|
186
|
+
|
|
171
187
|
self.log("QUEUED: #{response}") if response
|
|
172
188
|
|
|
173
189
|
response
|
|
@@ -114,6 +114,10 @@ module Postburner
|
|
|
114
114
|
validate :validate_job_class_exists!
|
|
115
115
|
validate :validate_cron_expression!, if: :cron?
|
|
116
116
|
|
|
117
|
+
# Instrumentation callbacks
|
|
118
|
+
after_create_commit :instrument_create
|
|
119
|
+
after_update_commit :instrument_update
|
|
120
|
+
|
|
117
121
|
# Scopes
|
|
118
122
|
scope :enabled, -> { where(enabled: true) }
|
|
119
123
|
scope :disabled, -> { where(enabled: false) }
|
|
@@ -348,6 +352,9 @@ module Postburner
|
|
|
348
352
|
# delayed queue will hold it until run_at. This ensures all future executions
|
|
349
353
|
# are already queued and ready to go.
|
|
350
354
|
#
|
|
355
|
+
# Instruments with ActiveSupport::Notifications:
|
|
356
|
+
# - create.schedule_execution.postburner: When execution is created
|
|
357
|
+
#
|
|
351
358
|
# @param after [Time, ScheduleExecution, nil] Calculate after this time/execution
|
|
352
359
|
# @return [ScheduleExecution, nil] The created execution, or nil if no more runs
|
|
353
360
|
#
|
|
@@ -358,6 +365,13 @@ module Postburner
|
|
|
358
365
|
return nil if execution.nil?
|
|
359
366
|
|
|
360
367
|
execution.save!
|
|
368
|
+
|
|
369
|
+
# Instrument execution creation
|
|
370
|
+
ActiveSupport::Notifications.instrument('create.schedule_execution.postburner', {
|
|
371
|
+
schedule: Postburner::Instrumentation.schedule_payload(self),
|
|
372
|
+
execution: Postburner::Instrumentation.execution_payload(execution)
|
|
373
|
+
})
|
|
374
|
+
|
|
361
375
|
execution.enqueue!
|
|
362
376
|
execution
|
|
363
377
|
end
|
|
@@ -718,5 +732,41 @@ module Postburner
|
|
|
718
732
|
n += 1
|
|
719
733
|
end
|
|
720
734
|
end
|
|
735
|
+
|
|
736
|
+
# Instrument schedule creation.
|
|
737
|
+
#
|
|
738
|
+
# Emits create.schedule.postburner event with schedule payload and changes.
|
|
739
|
+
#
|
|
740
|
+
# @return [void]
|
|
741
|
+
#
|
|
742
|
+
# @api private
|
|
743
|
+
#
|
|
744
|
+
def instrument_create
|
|
745
|
+
ActiveSupport::Notifications.instrument('create.schedule.postburner', {
|
|
746
|
+
schedule: Postburner::Instrumentation.schedule_payload(self),
|
|
747
|
+
changes: Postburner::Instrumentation.changes_payload(self, exclude: ['last_audit_at'])
|
|
748
|
+
})
|
|
749
|
+
end
|
|
750
|
+
|
|
751
|
+
# Instrument schedule update.
|
|
752
|
+
#
|
|
753
|
+
# Emits update.schedule.postburner event with schedule payload and changes.
|
|
754
|
+
# Excludes last_audit_at from changes to avoid noise from scheduler audits.
|
|
755
|
+
#
|
|
756
|
+
# @return [void]
|
|
757
|
+
#
|
|
758
|
+
# @api private
|
|
759
|
+
#
|
|
760
|
+
def instrument_update
|
|
761
|
+
changes = Postburner::Instrumentation.changes_payload(self, exclude: ['last_audit_at'])
|
|
762
|
+
|
|
763
|
+
# Skip instrumentation if only excluded attributes changed
|
|
764
|
+
return if changes.empty?
|
|
765
|
+
|
|
766
|
+
ActiveSupport::Notifications.instrument('update.schedule.postburner', {
|
|
767
|
+
schedule: Postburner::Instrumentation.schedule_payload(self),
|
|
768
|
+
changes: changes
|
|
769
|
+
})
|
|
770
|
+
end
|
|
721
771
|
end
|
|
722
772
|
end
|
|
@@ -99,6 +99,9 @@ module Postburner
|
|
|
99
99
|
#
|
|
100
100
|
# This method is idempotent - calling it multiple times will only enqueue once.
|
|
101
101
|
#
|
|
102
|
+
# Instruments with ActiveSupport::Notifications:
|
|
103
|
+
# - enqueue.schedule_execution.postburner: When execution is enqueued
|
|
104
|
+
#
|
|
102
105
|
# @return [void]
|
|
103
106
|
#
|
|
104
107
|
# @note Creating the next execution is the scheduler's responsibility via
|
|
@@ -128,6 +131,13 @@ module Postburner
|
|
|
128
131
|
enqueue_default_job!
|
|
129
132
|
end
|
|
130
133
|
end
|
|
134
|
+
|
|
135
|
+
# Instrument enqueue event (after transaction commits)
|
|
136
|
+
ActiveSupport::Notifications.instrument('enqueue.schedule_execution.postburner', {
|
|
137
|
+
schedule: Postburner::Instrumentation.schedule_payload(schedule),
|
|
138
|
+
execution: Postburner::Instrumentation.execution_payload(self.reload),
|
|
139
|
+
beanstalk_job_id: beanstalk_job_id
|
|
140
|
+
})
|
|
131
141
|
end
|
|
132
142
|
|
|
133
143
|
# Skip this execution.
|
|
@@ -138,6 +148,9 @@ module Postburner
|
|
|
138
148
|
# This is a destructive operation - skipped executions cannot be unskipped.
|
|
139
149
|
# A new execution must be created if needed.
|
|
140
150
|
#
|
|
151
|
+
# Instruments with ActiveSupport::Notifications:
|
|
152
|
+
# - skip.schedule_execution.postburner: When execution is skipped
|
|
153
|
+
#
|
|
141
154
|
# @return [Boolean] true if skipped successfully, false if already skipped
|
|
142
155
|
#
|
|
143
156
|
# @example Skip a future execution
|
|
@@ -156,6 +169,12 @@ module Postburner
|
|
|
156
169
|
update!(status: :skipped)
|
|
157
170
|
end
|
|
158
171
|
|
|
172
|
+
# Instrument skip event (after transaction commits)
|
|
173
|
+
ActiveSupport::Notifications.instrument('skip.schedule_execution.postburner', {
|
|
174
|
+
schedule: Postburner::Instrumentation.schedule_payload(schedule),
|
|
175
|
+
execution: Postburner::Instrumentation.execution_payload(self)
|
|
176
|
+
})
|
|
177
|
+
|
|
159
178
|
true
|
|
160
179
|
end
|
|
161
180
|
|
data/bin/postburner
CHANGED
|
@@ -3,14 +3,22 @@
|
|
|
3
3
|
|
|
4
4
|
# Postburner worker executable
|
|
5
5
|
#
|
|
6
|
-
# Loads configuration from YAML and starts the appropriate worker
|
|
6
|
+
# Loads configuration from YAML and starts the appropriate worker.
|
|
7
7
|
#
|
|
8
8
|
# Usage:
|
|
9
|
-
# bin/postburner [
|
|
9
|
+
# bin/postburner [options]
|
|
10
|
+
#
|
|
11
|
+
# Options:
|
|
12
|
+
# -c, --config PATH Path to YAML config (default: config/postburner.yml)
|
|
13
|
+
# -e, --env ENVIRONMENT Environment (default: RAILS_ENV, RACK_ENV, or development)
|
|
14
|
+
# -w, --worker WORKER Worker name (required if multiple workers defined)
|
|
15
|
+
# -q, --queues QUEUES Override configured queues (prefer defining workers)
|
|
10
16
|
#
|
|
11
17
|
# Examples:
|
|
12
18
|
# bin/postburner
|
|
13
|
-
# bin/postburner --
|
|
19
|
+
# bin/postburner --worker default
|
|
20
|
+
# bin/postburner --env production --worker imports
|
|
21
|
+
# bin/postburner --worker default --queues default,mailers
|
|
14
22
|
#
|
|
15
23
|
|
|
16
24
|
require 'optparse'
|
|
@@ -30,7 +38,7 @@ OptionParser.new do |opts|
|
|
|
30
38
|
options[:config] = path
|
|
31
39
|
end
|
|
32
40
|
|
|
33
|
-
opts.on('-e', '--env ENVIRONMENT', 'Environment (default: RAILS_ENV or development)') do |env|
|
|
41
|
+
opts.on('-e', '--env ENVIRONMENT', 'Environment (default: RAILS_ENV, RACK_ENV, or development)') do |env|
|
|
34
42
|
options[:env] = env
|
|
35
43
|
end
|
|
36
44
|
|
|
@@ -38,7 +46,7 @@ OptionParser.new do |opts|
|
|
|
38
46
|
options[:worker] = worker
|
|
39
47
|
end
|
|
40
48
|
|
|
41
|
-
opts.on('-q', '--queues QUEUES', '
|
|
49
|
+
opts.on('-q', '--queues QUEUES', 'Override configured queues, e.g. --queues default,mailers (prefer defining in yaml file, and selecting sets with --worker)') do |queues|
|
|
42
50
|
options[:queues] = queues.split(',').map(&:strip)
|
|
43
51
|
end
|
|
44
52
|
|