postburner 1.0.0.pre.5 → 1.0.0.pre.6
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 +85 -0
- data/app/concerns/postburner/insertion.rb +1 -2
- data/lib/postburner/configuration.rb +9 -2
- data/lib/postburner/connection.rb +62 -0
- data/lib/postburner/time_helpers.rb +4 -2
- data/lib/postburner/version.rb +1 -1
- data/lib/postburner.rb +103 -34
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a480ddab26850f1ecacc0f3c1ec75de82d8ac1f0acd2b4b7f0997dc5b3cc044c
|
|
4
|
+
data.tar.gz: 6d7ed3b8dd92df4d1064750c7eead44b8fa8d3c60887cb5c98771844a14f014d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 92f61d683537fa34a3aec8c7a052eb2313476fa2b647760d909022b28d0171db89b90c572b73af7eef6438bb1fc462f457d4b44bad1d249064993f68269de7e1
|
|
7
|
+
data.tar.gz: 495c9b4fba775507dd54666ab964bfa4d41fcc6608c3499ab5f4cc24b4f0af9a2cb4265b18331b566d61fce1318b1b1bc6a7ed9bc05d73619c5d5dd5dbc1711b
|
data/README.md
CHANGED
|
@@ -1352,6 +1352,91 @@ end
|
|
|
1352
1352
|
```
|
|
1353
1353
|
|
|
1354
1354
|
|
|
1355
|
+
### Tube Statistics and Management
|
|
1356
|
+
|
|
1357
|
+
Postburner provides methods to inspect and manage Beanstalkd tubes:
|
|
1358
|
+
|
|
1359
|
+
**View tube statistics:**
|
|
1360
|
+
|
|
1361
|
+
```ruby
|
|
1362
|
+
# View all tubes on the Beanstalkd server
|
|
1363
|
+
stats = Postburner.stats
|
|
1364
|
+
# => {
|
|
1365
|
+
# tubes: [
|
|
1366
|
+
# { name: "postburner.production.default", ready: 10, delayed: 5, buried: 0, reserved: 2, total: 17 },
|
|
1367
|
+
# { name: "postburner.production.critical", ready: 0, delayed: 0, buried: 0, reserved: 1, total: 1 }
|
|
1368
|
+
# ],
|
|
1369
|
+
# totals: { ready: 10, delayed: 5, buried: 0, reserved: 3, total: 18 }
|
|
1370
|
+
# }
|
|
1371
|
+
|
|
1372
|
+
# View specific tubes only
|
|
1373
|
+
stats = Postburner.stats(['postburner.production.critical'])
|
|
1374
|
+
# => { tubes: [...], totals: {...} }
|
|
1375
|
+
```
|
|
1376
|
+
|
|
1377
|
+
**Clear jobs from tubes:**
|
|
1378
|
+
|
|
1379
|
+
For safety, `clear_jobs!` requires you to explicitly specify which tubes to clear. This prevents accidentally clearing tubes from other applications sharing the same Beanstalkd server.
|
|
1380
|
+
|
|
1381
|
+
```ruby
|
|
1382
|
+
# Collect stats only (no clearing)
|
|
1383
|
+
result = Postburner.clear_jobs!
|
|
1384
|
+
# => { tubes: [...], totals: {...}, cleared: false }
|
|
1385
|
+
|
|
1386
|
+
# Clear specific tubes (must be in config/postburner.yml)
|
|
1387
|
+
result = Postburner.clear_jobs!(['postburner.production.default'])
|
|
1388
|
+
# => { tubes: [...], totals: {...}, cleared: true }
|
|
1389
|
+
|
|
1390
|
+
# Pretty-print JSON output
|
|
1391
|
+
Postburner.clear_jobs!(['postburner.production.default'], silent: false)
|
|
1392
|
+
# Outputs formatted JSON to stdout
|
|
1393
|
+
|
|
1394
|
+
# Silent mode (no output, just return data)
|
|
1395
|
+
result = Postburner.clear_jobs!(['postburner.production.default'], silent: true)
|
|
1396
|
+
```
|
|
1397
|
+
|
|
1398
|
+
**Safety validation:**
|
|
1399
|
+
|
|
1400
|
+
Only tubes defined in your loaded configuration can be cleared. This prevents mistakes in multi-tenant Beanstalkd environments:
|
|
1401
|
+
|
|
1402
|
+
```ruby
|
|
1403
|
+
# Error: trying to clear tube not in config
|
|
1404
|
+
Postburner.clear_jobs!(['postburner.production.other-app'])
|
|
1405
|
+
# => ArgumentError: Cannot clear tubes not in configuration.
|
|
1406
|
+
# Invalid tubes: postburner.production.other-app
|
|
1407
|
+
# Configured tubes: postburner.production.default, postburner.production.critical
|
|
1408
|
+
```
|
|
1409
|
+
|
|
1410
|
+
**Shortcut using watched_tube_names:**
|
|
1411
|
+
|
|
1412
|
+
Clear all configured tubes at once:
|
|
1413
|
+
|
|
1414
|
+
```ruby
|
|
1415
|
+
# Get all tubes from current configuration
|
|
1416
|
+
watched_tubes = Postburner.watched_tube_names
|
|
1417
|
+
# => ["postburner.production.default", "postburner.production.critical", "postburner.production.mailers"]
|
|
1418
|
+
|
|
1419
|
+
# Clear all configured tubes
|
|
1420
|
+
Postburner.clear_jobs!(watched_tubes, silent: true)
|
|
1421
|
+
# or
|
|
1422
|
+
Postburner.clear_jobs!(Postburner.watched_tube_names, silent: true)
|
|
1423
|
+
```
|
|
1424
|
+
|
|
1425
|
+
**Low-level Connection API:**
|
|
1426
|
+
|
|
1427
|
+
For programmatic use without output formatting, use `Connection#clear_tubes!`:
|
|
1428
|
+
|
|
1429
|
+
```ruby
|
|
1430
|
+
Postburner.connected do |conn|
|
|
1431
|
+
# Returns data only (no puts)
|
|
1432
|
+
result = conn.clear_tubes!(Postburner.watched_tube_names)
|
|
1433
|
+
# => { tubes: [...], totals: {...}, cleared: true }
|
|
1434
|
+
|
|
1435
|
+
# Same validation - must be in configuration
|
|
1436
|
+
result = conn.clear_tubes!(['postburner.production.default'])
|
|
1437
|
+
end
|
|
1438
|
+
```
|
|
1439
|
+
|
|
1355
1440
|
## Web UI
|
|
1356
1441
|
|
|
1357
1442
|
Mount the inspection interface:
|
|
@@ -159,9 +159,8 @@ module Postburner
|
|
|
159
159
|
#debugger
|
|
160
160
|
|
|
161
161
|
# Response must be a hash with an :id key (value can be nil)
|
|
162
|
-
# Backburner returns symbol keys
|
|
163
162
|
unless response.is_a?(Hash) && response.key?(:id)
|
|
164
|
-
raise MalformedResponse, "Missing :id key in response: #{response.inspect}"
|
|
163
|
+
raise Postburner::Job::MalformedResponse, "Missing :id key in response: #{response.inspect}"
|
|
165
164
|
end
|
|
166
165
|
|
|
167
166
|
persist_metadata!(bkid: response[:id])
|
|
@@ -99,11 +99,18 @@ module Postburner
|
|
|
99
99
|
if workers.size == 1
|
|
100
100
|
worker_name = workers.keys.first
|
|
101
101
|
else
|
|
102
|
-
raise ArgumentError,
|
|
102
|
+
raise ArgumentError, <<~ERROR
|
|
103
|
+
Configuration has multiple workers, but --worker not specified
|
|
104
|
+
Available workers: #{workers.keys.join(', ')}
|
|
105
|
+
Usage: bin/postburner --worker <name>
|
|
106
|
+
ERROR
|
|
103
107
|
end
|
|
104
108
|
else
|
|
105
109
|
unless workers.key?(worker_name)
|
|
106
|
-
raise ArgumentError,
|
|
110
|
+
raise ArgumentError, <<~ERROR
|
|
111
|
+
Worker '#{worker_name}' not found in #{path}
|
|
112
|
+
Available workers: #{workers.keys.join(', ')}
|
|
113
|
+
ERROR
|
|
107
114
|
end
|
|
108
115
|
end
|
|
109
116
|
|
|
@@ -88,6 +88,68 @@ module Postburner
|
|
|
88
88
|
@pool = nil
|
|
89
89
|
end
|
|
90
90
|
|
|
91
|
+
# Clears jobs from specified tubes or collects stats for all tubes.
|
|
92
|
+
#
|
|
93
|
+
# Low-level method that returns data only (no output to stdout).
|
|
94
|
+
# Delegates to Postburner.stats for collecting statistics.
|
|
95
|
+
# For user-facing output, use Postburner.clear_jobs! instead.
|
|
96
|
+
#
|
|
97
|
+
# SAFETY: Only allows clearing tubes that are defined in the loaded
|
|
98
|
+
# configuration (watched_tube_names). This prevents accidentally clearing
|
|
99
|
+
# tubes from other applications or environments.
|
|
100
|
+
#
|
|
101
|
+
# @param tube_names [Array<String>, nil] Array of tube names to clear, or nil to only collect stats
|
|
102
|
+
#
|
|
103
|
+
# @return [Hash] Statistics and results with keys:
|
|
104
|
+
# - tubes: Array of hashes with per-tube stats
|
|
105
|
+
# - totals: Hash with aggregated counts across all tubes
|
|
106
|
+
# - cleared: Boolean indicating if tubes were actually cleared
|
|
107
|
+
#
|
|
108
|
+
# @raise [ArgumentError] if tube_names contains tubes not in watched_tube_names
|
|
109
|
+
#
|
|
110
|
+
# @example Collect stats only (no clearing)
|
|
111
|
+
# result = conn.clear_tubes!
|
|
112
|
+
# result[:totals][:total] # => 42
|
|
113
|
+
#
|
|
114
|
+
# @example Clear configured tubes only
|
|
115
|
+
# result = conn.clear_tubes!(Postburner.watched_tube_names)
|
|
116
|
+
# result[:cleared] # => true
|
|
117
|
+
#
|
|
118
|
+
# @example Invalid tube raises error
|
|
119
|
+
# conn.clear_tubes!(['random-tube'])
|
|
120
|
+
# # => ArgumentError: Cannot clear tubes not in configuration
|
|
121
|
+
#
|
|
122
|
+
def clear_tubes!(tube_names = nil)
|
|
123
|
+
ensure_connected!
|
|
124
|
+
|
|
125
|
+
# Validate that tubes to clear are in the loaded configuration
|
|
126
|
+
if tube_names&.any?
|
|
127
|
+
watched = Postburner.watched_tube_names
|
|
128
|
+
invalid_tubes = tube_names - watched
|
|
129
|
+
|
|
130
|
+
if invalid_tubes.any?
|
|
131
|
+
raise ArgumentError, <<~ERROR
|
|
132
|
+
Cannot clear tubes not in configuration.
|
|
133
|
+
Invalid tubes: #{invalid_tubes.join(', ')}
|
|
134
|
+
Configured tubes: #{watched.join(', ')}
|
|
135
|
+
ERROR
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
# Get stats using Postburner.stats
|
|
140
|
+
result = Postburner.stats(tube_names)
|
|
141
|
+
result[:cleared] = tube_names&.any? ? true : false
|
|
142
|
+
|
|
143
|
+
# Actually clear if tube names were provided and validated
|
|
144
|
+
if tube_names&.any?
|
|
145
|
+
tube_names.each do |tube_name|
|
|
146
|
+
tubes[tube_name].clear
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
result
|
|
151
|
+
end
|
|
152
|
+
|
|
91
153
|
private
|
|
92
154
|
|
|
93
155
|
# Establishes connection to Beanstalkd.
|
|
@@ -64,8 +64,10 @@ module Postburner
|
|
|
64
64
|
#
|
|
65
65
|
def travel_to(time, &block)
|
|
66
66
|
unless defined?(ActiveSupport::Testing::TimeHelpers)
|
|
67
|
-
raise
|
|
68
|
-
|
|
67
|
+
raise <<~ERROR
|
|
68
|
+
ActiveSupport::Testing::TimeHelpers not available.
|
|
69
|
+
Postburner::TimeHelpers requires Rails testing helpers for time travel.
|
|
70
|
+
ERROR
|
|
69
71
|
end
|
|
70
72
|
|
|
71
73
|
helper = Object.new.extend(ActiveSupport::Testing::TimeHelpers)
|
data/lib/postburner/version.rb
CHANGED
data/lib/postburner.rb
CHANGED
|
@@ -375,25 +375,50 @@ module Postburner
|
|
|
375
375
|
end
|
|
376
376
|
end
|
|
377
377
|
|
|
378
|
-
#
|
|
378
|
+
# Clears jobs from specified tubes or shows stats for all tubes.
|
|
379
379
|
#
|
|
380
|
-
#
|
|
381
|
-
#
|
|
380
|
+
# High-level method with formatted output. Delegates to Connection#clear_tubes!
|
|
381
|
+
# for the actual work, then pretty-prints the results.
|
|
382
382
|
#
|
|
383
|
-
#
|
|
383
|
+
# SAFETY: Only allows clearing tubes that are defined in the loaded
|
|
384
|
+
# configuration. This prevents accidentally clearing tubes from other
|
|
385
|
+
# applications or environments sharing the same Beanstalkd server.
|
|
384
386
|
#
|
|
385
|
-
# @
|
|
387
|
+
# @param tube_names [Array<String>, nil] Array of tube names to clear, or nil to only show stats
|
|
388
|
+
# @param silent [Boolean] If true, suppress output to stdout (default: false)
|
|
386
389
|
#
|
|
387
|
-
# @
|
|
388
|
-
#
|
|
390
|
+
# @return [Hash] Statistics and results (see Connection#clear_tubes!)
|
|
391
|
+
#
|
|
392
|
+
# @raise [ArgumentError] if tube_names contains tubes not in watched_tube_names
|
|
393
|
+
#
|
|
394
|
+
# @example Show stats only (no clearing) - SAFE
|
|
395
|
+
# Postburner.clear_jobs!
|
|
396
|
+
# # Shows stats for ALL tubes on Beanstalkd, but doesn't clear anything
|
|
397
|
+
#
|
|
398
|
+
# @example Clear watched tubes only - SAFE
|
|
399
|
+
# Postburner.clear_jobs!(Postburner.watched_tube_names)
|
|
400
|
+
# # Only clears tubes defined in your config
|
|
389
401
|
#
|
|
390
|
-
# @
|
|
391
|
-
#
|
|
402
|
+
# @example Trying to clear unconfigured tube - RAISES ERROR
|
|
403
|
+
# Postburner.clear_jobs!(['some-other-app-tube'])
|
|
404
|
+
# # => ArgumentError: Cannot clear tubes not in configuration
|
|
392
405
|
#
|
|
393
|
-
|
|
394
|
-
|
|
406
|
+
# @example Silent mode (programmatic use)
|
|
407
|
+
# result = Postburner.clear_jobs!(Postburner.watched_tube_names, silent: true)
|
|
408
|
+
# result[:totals][:total] # => 42
|
|
409
|
+
#
|
|
410
|
+
# @see Connection#clear_tubes!
|
|
411
|
+
#
|
|
412
|
+
def self.clear_jobs!(tube_names = nil, silent: false)
|
|
413
|
+
require 'json'
|
|
414
|
+
|
|
415
|
+
result = connection.clear_tubes!(tube_names)
|
|
416
|
+
|
|
417
|
+
unless silent
|
|
418
|
+
puts JSON.pretty_generate(result)
|
|
419
|
+
end
|
|
395
420
|
|
|
396
|
-
|
|
421
|
+
result
|
|
397
422
|
end
|
|
398
423
|
|
|
399
424
|
# Returns array of watched tube names with environment prefix.
|
|
@@ -423,38 +448,82 @@ module Postburner
|
|
|
423
448
|
@__watched_tubes ||= watched_tube_names.map { |tube_name| connection.tubes[tube_name] }
|
|
424
449
|
end
|
|
425
450
|
|
|
426
|
-
# Returns statistics
|
|
451
|
+
# Returns detailed statistics about Beanstalkd tubes.
|
|
427
452
|
#
|
|
428
|
-
#
|
|
429
|
-
#
|
|
453
|
+
# Collects job counts (ready, delayed, buried, reserved) for each tube
|
|
454
|
+
# and provides aggregate totals across all tubes.
|
|
430
455
|
#
|
|
431
|
-
#
|
|
432
|
-
# - tube.stats - Tube statistics hash (current-jobs-ready, current-jobs-buried, etc.)
|
|
433
|
-
# - tube.peek_ready - Next ready job
|
|
434
|
-
# - tube.peek_delayed - Next delayed job
|
|
435
|
-
# - tube.peek_buried - Next buried job
|
|
436
|
-
# - tube.kick(n) - Kick n buried jobs back to ready
|
|
437
|
-
# - tube.pause(delay) - Pause tube for delay seconds
|
|
438
|
-
# - tube.clear - Delete all jobs in tube
|
|
456
|
+
# @param tube_names [Array<String>, nil] Specific tube names to inspect, or nil for all tubes
|
|
439
457
|
#
|
|
440
|
-
# @return [Hash] Statistics hash with
|
|
441
|
-
# -
|
|
442
|
-
# -
|
|
458
|
+
# @return [Hash] Statistics hash with keys:
|
|
459
|
+
# - tubes: Array of hashes with per-tube stats (name, ready, delayed, buried, reserved, total)
|
|
460
|
+
# - totals: Hash with aggregated counts across all tubes
|
|
443
461
|
#
|
|
444
462
|
# @raise [Beaneater::NotConnected] if connection to Beanstalkd fails
|
|
445
463
|
#
|
|
446
|
-
# @example
|
|
464
|
+
# @example Get stats for all tubes
|
|
447
465
|
# stats = Postburner.stats
|
|
448
|
-
# stats[:
|
|
449
|
-
# stats[:tubes].first
|
|
466
|
+
# stats[:totals][:total] # => 42
|
|
467
|
+
# stats[:tubes].first[:name] # => "default"
|
|
468
|
+
#
|
|
469
|
+
# @example Get stats for specific tubes
|
|
470
|
+
# stats = Postburner.stats(Postburner.watched_tube_names)
|
|
471
|
+
# stats[:tubes].size # => 3
|
|
450
472
|
#
|
|
451
|
-
def self.stats
|
|
473
|
+
def self.stats(tube_names = nil)
|
|
452
474
|
connected do |conn|
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
475
|
+
# Get tubes to inspect
|
|
476
|
+
tubes_to_inspect = if tube_names&.any?
|
|
477
|
+
tube_names.map { |name| conn.tubes[name] }
|
|
478
|
+
else
|
|
479
|
+
conn.beanstalk.tubes.all
|
|
480
|
+
end
|
|
481
|
+
|
|
482
|
+
result = {
|
|
483
|
+
tubes: [],
|
|
484
|
+
totals: {
|
|
485
|
+
ready: 0,
|
|
486
|
+
delayed: 0,
|
|
487
|
+
buried: 0,
|
|
488
|
+
reserved: 0,
|
|
489
|
+
total: 0
|
|
490
|
+
}
|
|
457
491
|
}
|
|
492
|
+
|
|
493
|
+
# Collect stats from each tube
|
|
494
|
+
tubes_to_inspect.each do |tube|
|
|
495
|
+
begin
|
|
496
|
+
stats = tube.stats
|
|
497
|
+
# Beaneater returns a StatStruct; access the underlying hash
|
|
498
|
+
stats_hash = stats.instance_variable_get(:@hash) || {}
|
|
499
|
+
|
|
500
|
+
tube_data = {
|
|
501
|
+
name: tube.name,
|
|
502
|
+
ready: stats_hash['current-jobs-ready'] || 0,
|
|
503
|
+
delayed: stats_hash['current-jobs-delayed'] || 0,
|
|
504
|
+
buried: stats_hash['current-jobs-buried'] || 0,
|
|
505
|
+
reserved: stats_hash['current-jobs-reserved'] || 0,
|
|
506
|
+
total: (stats_hash['current-jobs-ready'] || 0) +
|
|
507
|
+
(stats_hash['current-jobs-delayed'] || 0) +
|
|
508
|
+
(stats_hash['current-jobs-buried'] || 0) +
|
|
509
|
+
(stats_hash['current-jobs-reserved'] || 0)
|
|
510
|
+
}
|
|
511
|
+
rescue Beaneater::NotFoundError
|
|
512
|
+
# Tube doesn't exist yet, skip it
|
|
513
|
+
next
|
|
514
|
+
end
|
|
515
|
+
|
|
516
|
+
result[:tubes] << tube_data
|
|
517
|
+
|
|
518
|
+
# Aggregate totals
|
|
519
|
+
result[:totals][:ready] += tube_data[:ready]
|
|
520
|
+
result[:totals][:delayed] += tube_data[:delayed]
|
|
521
|
+
result[:totals][:buried] += tube_data[:buried]
|
|
522
|
+
result[:totals][:reserved] += tube_data[:reserved]
|
|
523
|
+
result[:totals][:total] += tube_data[:total]
|
|
524
|
+
end
|
|
525
|
+
|
|
526
|
+
result
|
|
458
527
|
end
|
|
459
528
|
end
|
|
460
529
|
end
|