pgbus 0.8.3 → 0.9.0
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/app/controllers/pgbus/batches_controller.rb +15 -0
- data/app/helpers/pgbus/application_helper.rb +12 -0
- data/app/views/layouts/pgbus/application.html.erb +2 -0
- data/app/views/pgbus/batches/_batches_table.html.erb +53 -0
- data/app/views/pgbus/batches/index.html.erb +8 -0
- data/app/views/pgbus/batches/show.html.erb +90 -0
- data/config/locales/da.yml +34 -0
- data/config/locales/de.yml +34 -0
- data/config/locales/en.yml +34 -0
- data/config/locales/es.yml +34 -0
- data/config/locales/fi.yml +34 -0
- data/config/locales/fr.yml +34 -0
- data/config/locales/it.yml +34 -0
- data/config/locales/ja.yml +34 -0
- data/config/locales/nb.yml +34 -0
- data/config/locales/nl.yml +34 -0
- data/config/locales/pt.yml +34 -0
- data/config/locales/sv.yml +34 -0
- data/config/routes.rb +1 -0
- data/lib/pgbus/client.rb +102 -4
- data/lib/pgbus/configuration.rb +80 -1
- data/lib/pgbus/process/supervisor.rb +2 -1
- data/lib/pgbus/process/worker.rb +38 -1
- data/lib/pgbus/serializer.rb +1 -1
- data/lib/pgbus/version.rb +1 -1
- data/lib/pgbus/web/data_source.rb +96 -0
- data/lib/pgbus/web/streamer/instance.rb +1 -1
- data/lib/tasks/pgbus_queues.rake +54 -0
- metadata +8 -3
|
@@ -590,6 +590,43 @@ module Pgbus
|
|
|
590
590
|
[]
|
|
591
591
|
end
|
|
592
592
|
|
|
593
|
+
# Batches
|
|
594
|
+
def batches(limit: 100)
|
|
595
|
+
BatchEntry.order(created_at: :desc).limit(limit).map { |r| format_batch(r) }
|
|
596
|
+
rescue StandardError => e
|
|
597
|
+
Pgbus.logger.debug { "[Pgbus::Web] Error fetching batches: #{e.message}" }
|
|
598
|
+
[]
|
|
599
|
+
end
|
|
600
|
+
|
|
601
|
+
def batch_detail(batch_id)
|
|
602
|
+
record = BatchEntry.find_by(batch_id: batch_id)
|
|
603
|
+
return nil unless record
|
|
604
|
+
|
|
605
|
+
format_batch(record).merge(
|
|
606
|
+
properties: record.properties,
|
|
607
|
+
on_finish_class: record.on_finish_class,
|
|
608
|
+
on_success_class: record.on_success_class,
|
|
609
|
+
on_discard_class: record.on_discard_class
|
|
610
|
+
)
|
|
611
|
+
rescue StandardError => e
|
|
612
|
+
Pgbus.logger.debug { "[Pgbus::Web] Error fetching batch #{batch_id}: #{e.message}" }
|
|
613
|
+
nil
|
|
614
|
+
end
|
|
615
|
+
|
|
616
|
+
def batches_count
|
|
617
|
+
BatchEntry.count
|
|
618
|
+
rescue StandardError => e
|
|
619
|
+
Pgbus.logger.debug { "[Pgbus::Web] Error counting batches: #{e.message}" }
|
|
620
|
+
0
|
|
621
|
+
end
|
|
622
|
+
|
|
623
|
+
def active_batches_count
|
|
624
|
+
BatchEntry.where.not(status: "finished").count
|
|
625
|
+
rescue StandardError => e
|
|
626
|
+
Pgbus.logger.debug { "[Pgbus::Web] Error counting active batches: #{e.message}" }
|
|
627
|
+
0
|
|
628
|
+
end
|
|
629
|
+
|
|
593
630
|
# Job stats
|
|
594
631
|
def job_stats_summary(minutes: 60)
|
|
595
632
|
JobStat.summary(minutes: minutes)
|
|
@@ -874,6 +911,33 @@ module Pgbus
|
|
|
874
911
|
[]
|
|
875
912
|
end
|
|
876
913
|
|
|
914
|
+
# NOTIFY throttle status for all queues with notifications enabled.
|
|
915
|
+
# Returns an array of hashes: { queue_name:, throttle_interval_ms:, last_notified_at: }
|
|
916
|
+
def notify_throttles
|
|
917
|
+
@client.list_notify_insert_throttles.map do |throttle|
|
|
918
|
+
{
|
|
919
|
+
queue_name: throttle.queue_name,
|
|
920
|
+
throttle_interval_ms: throttle.throttle_interval_ms,
|
|
921
|
+
last_notified_at: throttle.last_notified_at
|
|
922
|
+
}
|
|
923
|
+
end
|
|
924
|
+
rescue StandardError => e
|
|
925
|
+
Pgbus.logger.debug { "[Pgbus::Web] Error fetching notify throttles: #{e.message}" }
|
|
926
|
+
[]
|
|
927
|
+
end
|
|
928
|
+
|
|
929
|
+
# FIFO group head sampling for a specific queue.
|
|
930
|
+
# Returns the oldest visible message from each distinct group (up to qty).
|
|
931
|
+
# Useful for detecting head-of-line stalls in multi-tenant queues.
|
|
932
|
+
def queue_group_heads(queue_name, qty: 20)
|
|
933
|
+
logical = logical_queue_name(queue_name)
|
|
934
|
+
messages = @client.read_grouped_head(logical, qty: qty) || []
|
|
935
|
+
messages.map { |m| format_pgmq_message(m, queue_name) }
|
|
936
|
+
rescue StandardError => e
|
|
937
|
+
Pgbus.logger.debug { "[Pgbus::Web] Error fetching group heads for #{queue_name}: #{e.message}" }
|
|
938
|
+
[]
|
|
939
|
+
end
|
|
940
|
+
|
|
877
941
|
private
|
|
878
942
|
|
|
879
943
|
def connection
|
|
@@ -1114,6 +1178,19 @@ module Pgbus
|
|
|
1114
1178
|
}
|
|
1115
1179
|
end
|
|
1116
1180
|
|
|
1181
|
+
def format_pgmq_message(msg, queue_name)
|
|
1182
|
+
{
|
|
1183
|
+
msg_id: msg.msg_id.to_i,
|
|
1184
|
+
read_ct: msg.read_ct.to_i,
|
|
1185
|
+
enqueued_at: msg.enqueued_at,
|
|
1186
|
+
last_read_at: msg.respond_to?(:last_read_at) ? msg.last_read_at : nil,
|
|
1187
|
+
vt: msg.respond_to?(:vt) ? msg.vt : nil,
|
|
1188
|
+
message: msg.message,
|
|
1189
|
+
headers: msg.headers,
|
|
1190
|
+
queue_name: queue_name
|
|
1191
|
+
}
|
|
1192
|
+
end
|
|
1193
|
+
|
|
1117
1194
|
def format_process(row)
|
|
1118
1195
|
heartbeat = row["last_heartbeat_at"]
|
|
1119
1196
|
heartbeat_time = heartbeat.is_a?(String) ? Time.parse(heartbeat) : heartbeat
|
|
@@ -1131,6 +1208,25 @@ module Pgbus
|
|
|
1131
1208
|
}
|
|
1132
1209
|
end
|
|
1133
1210
|
|
|
1211
|
+
def format_batch(record)
|
|
1212
|
+
total = record.total_jobs
|
|
1213
|
+
done = record.completed_jobs + record.discarded_jobs
|
|
1214
|
+
pct = total.positive? ? ((done * 100) / total) : 100
|
|
1215
|
+
|
|
1216
|
+
{
|
|
1217
|
+
batch_id: record.batch_id,
|
|
1218
|
+
description: record.description,
|
|
1219
|
+
status: record.status,
|
|
1220
|
+
total_jobs: total,
|
|
1221
|
+
completed_jobs: record.completed_jobs,
|
|
1222
|
+
discarded_jobs: record.discarded_jobs,
|
|
1223
|
+
failed_jobs: record.failed_jobs,
|
|
1224
|
+
progress_pct: pct,
|
|
1225
|
+
created_at: record.created_at,
|
|
1226
|
+
finished_at: record.finished_at
|
|
1227
|
+
}
|
|
1228
|
+
end
|
|
1229
|
+
|
|
1134
1230
|
def sanitize_name(name)
|
|
1135
1231
|
QueueNameValidator.sanitize!(name)
|
|
1136
1232
|
end
|
|
@@ -145,7 +145,7 @@ module Pgbus
|
|
|
145
145
|
|
|
146
146
|
def build_pg_connection
|
|
147
147
|
require "pg" unless defined?(::PG::Connection)
|
|
148
|
-
opts = @config.
|
|
148
|
+
opts = @config.streams_connection_options
|
|
149
149
|
case opts
|
|
150
150
|
when String then ::PG.connect(opts)
|
|
151
151
|
when Hash then ::PG.connect(**opts)
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
namespace :pgbus do
|
|
4
|
+
namespace :queues do
|
|
5
|
+
desc "Create FIFO indexes on all pgbus queues (required for grouped reads)"
|
|
6
|
+
task fifo_indexes: :environment do
|
|
7
|
+
puts "Creating FIFO indexes on all pgbus queues..."
|
|
8
|
+
Pgbus.client.create_fifo_indexes_all
|
|
9
|
+
puts "Done. FIFO indexes created on all queues."
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
desc "Create FIFO index on a specific queue (QUEUE=name)"
|
|
13
|
+
task fifo_index: :environment do
|
|
14
|
+
queue = ENV.fetch("QUEUE") do
|
|
15
|
+
abort "Usage: rake pgbus:queues:fifo_index QUEUE=<queue_name>"
|
|
16
|
+
end
|
|
17
|
+
puts "Creating FIFO index on queue '#{queue}'..."
|
|
18
|
+
Pgbus.client.create_fifo_index(queue)
|
|
19
|
+
puts "Done."
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
namespace :archives do
|
|
24
|
+
desc "Convert a queue's archive table to pg_partman-managed partitions (QUEUE=name)"
|
|
25
|
+
task partition: :environment do
|
|
26
|
+
queue = ENV.fetch("QUEUE") do
|
|
27
|
+
abort "Usage: rake pgbus:archives:partition QUEUE=<queue_name> " \
|
|
28
|
+
"[INTERVAL=10000] [RETENTION=100000] [LEADING_PARTITION=10]"
|
|
29
|
+
end
|
|
30
|
+
interval = ENV.fetch("INTERVAL", "10000")
|
|
31
|
+
retention = ENV.fetch("RETENTION", "100000")
|
|
32
|
+
leading_raw = ENV.fetch("LEADING_PARTITION", "10")
|
|
33
|
+
leading = begin
|
|
34
|
+
Integer(leading_raw, 10)
|
|
35
|
+
rescue ArgumentError, TypeError
|
|
36
|
+
abort "LEADING_PARTITION must be a positive integer, got #{leading_raw.inspect}"
|
|
37
|
+
end
|
|
38
|
+
abort "LEADING_PARTITION must be a positive integer" if leading <= 0
|
|
39
|
+
|
|
40
|
+
puts "Converting archive table for queue '#{queue}' to partitioned..."
|
|
41
|
+
puts " Partition interval: #{interval}"
|
|
42
|
+
puts " Retention interval: #{retention}"
|
|
43
|
+
puts " Leading partitions: #{leading}"
|
|
44
|
+
|
|
45
|
+
Pgbus.client.convert_archive_partitioned(
|
|
46
|
+
queue,
|
|
47
|
+
partition_interval: interval,
|
|
48
|
+
retention_interval: retention,
|
|
49
|
+
leading_partition: leading
|
|
50
|
+
)
|
|
51
|
+
puts "Done. Archive table is now partitioned."
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: pgbus
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.9.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Mikael Henriksson
|
|
@@ -63,14 +63,14 @@ dependencies:
|
|
|
63
63
|
requirements:
|
|
64
64
|
- - "~>"
|
|
65
65
|
- !ruby/object:Gem::Version
|
|
66
|
-
version:
|
|
66
|
+
version: 0.7.0
|
|
67
67
|
type: :runtime
|
|
68
68
|
prerelease: false
|
|
69
69
|
version_requirements: !ruby/object:Gem::Requirement
|
|
70
70
|
requirements:
|
|
71
71
|
- - "~>"
|
|
72
72
|
- !ruby/object:Gem::Version
|
|
73
|
-
version:
|
|
73
|
+
version: 0.7.0
|
|
74
74
|
- !ruby/object:Gem::Dependency
|
|
75
75
|
name: railties
|
|
76
76
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -126,6 +126,7 @@ files:
|
|
|
126
126
|
- app/controllers/pgbus/api/metrics_controller.rb
|
|
127
127
|
- app/controllers/pgbus/api/stats_controller.rb
|
|
128
128
|
- app/controllers/pgbus/application_controller.rb
|
|
129
|
+
- app/controllers/pgbus/batches_controller.rb
|
|
129
130
|
- app/controllers/pgbus/dashboard_controller.rb
|
|
130
131
|
- app/controllers/pgbus/dead_letter_controller.rb
|
|
131
132
|
- app/controllers/pgbus/events_controller.rb
|
|
@@ -161,6 +162,9 @@ files:
|
|
|
161
162
|
- app/models/pgbus/stream_stat.rb
|
|
162
163
|
- app/models/pgbus/uniqueness_key.rb
|
|
163
164
|
- app/views/layouts/pgbus/application.html.erb
|
|
165
|
+
- app/views/pgbus/batches/_batches_table.html.erb
|
|
166
|
+
- app/views/pgbus/batches/index.html.erb
|
|
167
|
+
- app/views/pgbus/batches/show.html.erb
|
|
164
168
|
- app/views/pgbus/dashboard/_processes_table.html.erb
|
|
165
169
|
- app/views/pgbus/dashboard/_queue_health.html.erb
|
|
166
170
|
- app/views/pgbus/dashboard/_queues_table.html.erb
|
|
@@ -343,6 +347,7 @@ files:
|
|
|
343
347
|
- lib/puma/plugin/pgbus_streams.rb
|
|
344
348
|
- lib/tasks/pgbus_autovacuum.rake
|
|
345
349
|
- lib/tasks/pgbus_pgmq.rake
|
|
350
|
+
- lib/tasks/pgbus_queues.rake
|
|
346
351
|
- lib/tasks/pgbus_streams.rake
|
|
347
352
|
homepage: https://github.com/mhenrixon/pgbus
|
|
348
353
|
licenses:
|