pgbus 0.16.6 → 0.17.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/CHANGELOG.md +6 -0
- data/README.md +8 -0
- data/Rakefile +3 -168
- data/lib/generators/pgbus/templates/upgrade_pgmq.rb.erb +22 -0
- data/lib/pgbus/event_bus/claim_beat.rb +80 -0
- data/lib/pgbus/event_bus/handler.rb +123 -34
- data/lib/pgbus/event_bus/publisher.rb +1 -1
- data/lib/pgbus/event_bus/registry.rb +24 -1
- data/lib/pgbus/instrumentation.rb +4 -0
- data/lib/pgbus/metrics/subscriber.rb +14 -0
- data/lib/pgbus/pgmq_schema/fixups/pgmq_v1.13.0.sql +49 -0
- data/lib/pgbus/pgmq_schema/pgmq_v1.13.0.sql +2193 -0
- data/lib/pgbus/pgmq_schema.rb +41 -3
- data/lib/pgbus/process/consumer.rb +71 -4
- data/lib/pgbus/testing.rb +1 -1
- data/lib/pgbus/version.rb +1 -1
- data/lib/pgbus/visibility_heartbeat.rb +23 -4
- metadata +4 -1
|
@@ -33,6 +33,7 @@ module Pgbus
|
|
|
33
33
|
subscribe("pgbus.job_visibility_extended") { |event| on_job_visibility_extended(event) },
|
|
34
34
|
subscribe("pgbus.event_processed") { |event| on_event_processed(event) },
|
|
35
35
|
subscribe("pgbus.event_failed") { |event| on_event_failed(event) },
|
|
36
|
+
subscribe("pgbus.event_skipped") { |event| on_event_skipped(event) },
|
|
36
37
|
subscribe("pgbus.client.send_message") { |event| on_send_message(event) },
|
|
37
38
|
subscribe("pgbus.client.send_batch") { |event| on_send_batch(event) },
|
|
38
39
|
subscribe("pgbus.client.read_batch") { |event| on_read_batch(event) },
|
|
@@ -139,6 +140,19 @@ module Pgbus
|
|
|
139
140
|
)
|
|
140
141
|
end
|
|
141
142
|
|
|
143
|
+
# An idempotent handler that did not run this delivery. `reason` is what
|
|
144
|
+
# makes the skip readable: :completed/:cached is deduplication working,
|
|
145
|
+
# :owned means a second delivery arrived while the holder was still
|
|
146
|
+
# running and was deferred to it (issue #470).
|
|
147
|
+
def on_event_skipped(event)
|
|
148
|
+
payload = event.payload
|
|
149
|
+
backend.increment(
|
|
150
|
+
"#{METRIC_PREFIX}event_count", 1,
|
|
151
|
+
compact(handler: payload[:handler], routing_key: payload[:routing_key],
|
|
152
|
+
status: "skipped", reason: payload[:reason])
|
|
153
|
+
)
|
|
154
|
+
end
|
|
155
|
+
|
|
142
156
|
# ── Client (PGMQ wrapper) ─────────────────────────────────────────
|
|
143
157
|
|
|
144
158
|
def on_send_message(event)
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
-- PGMQ 1.13.0 table fixup.
|
|
2
|
+
--
|
|
3
|
+
-- Adapted from the upstream migration
|
|
4
|
+
-- pgmq-extension/sql/pgmq--1.12.0--1.13.0.sql at tag v1.13.0
|
|
5
|
+
-- (blob a380ee56e856c5799dcd1486342ce910b96da64e), which is the only part of
|
|
6
|
+
-- that file pgbus's upgrade cannot already reproduce: dropping every function
|
|
7
|
+
-- and composite type and re-running the target schema recreates functions and
|
|
8
|
+
-- types, but never touches an existing table.
|
|
9
|
+
--
|
|
10
|
+
-- One deliberate deviation from upstream: the guard resolves the queue table by
|
|
11
|
+
-- OID via to_regclass instead of matching information_schema.columns.table_name
|
|
12
|
+
-- against the formatted name. See the comment on the guard for why.
|
|
13
|
+
--
|
|
14
|
+
-- Every file in this directory MUST be idempotent and self-guarded. The
|
|
15
|
+
-- upgrade migration applies each fixup between the recorded installed version
|
|
16
|
+
-- and the target, and an install whose version was never recorded gets all of
|
|
17
|
+
-- them, so a fixup can be replayed against a database that already has it.
|
|
18
|
+
|
|
19
|
+
-- Partitioned queues: msg_id becomes GENERATED BY DEFAULT AS IDENTITY.
|
|
20
|
+
-- pg_partman's partition_data_* tooling moves rows out of the default
|
|
21
|
+
-- partition by inserting them with their existing msg_id, which
|
|
22
|
+
-- GENERATED ALWAYS refuses. pgmq's own writers never supply msg_id, so this
|
|
23
|
+
-- changes nothing for them.
|
|
24
|
+
DO $$
|
|
25
|
+
DECLARE
|
|
26
|
+
queue_record RECORD;
|
|
27
|
+
qtable TEXT;
|
|
28
|
+
BEGIN
|
|
29
|
+
FOR queue_record IN SELECT queue_name FROM pgmq.meta WHERE is_partitioned LOOP
|
|
30
|
+
qtable := pgmq.format_table_name(queue_record.queue_name, 'q');
|
|
31
|
+
|
|
32
|
+
-- Resolved by OID rather than by comparing qtable to a catalog name:
|
|
33
|
+
-- validate_queue_name caps the queue at 47 *characters*, but PostgreSQL
|
|
34
|
+
-- truncates identifiers at 63 *bytes*, so a multibyte name can produce a
|
|
35
|
+
-- qtable string that never equals the stored relation name. A name
|
|
36
|
+
-- comparison would silently skip such a queue and leave msg_id at
|
|
37
|
+
-- ALWAYS, which is the exact failure this fixup exists to prevent.
|
|
38
|
+
IF EXISTS (
|
|
39
|
+
SELECT 1
|
|
40
|
+
FROM pg_catalog.pg_attribute
|
|
41
|
+
WHERE attrelid = pg_catalog.to_regclass(FORMAT('pgmq.%I', qtable))
|
|
42
|
+
AND attname = 'msg_id'
|
|
43
|
+
AND attidentity = 'a'
|
|
44
|
+
) THEN
|
|
45
|
+
EXECUTE FORMAT('ALTER TABLE pgmq.%I ALTER COLUMN msg_id SET GENERATED BY DEFAULT', qtable);
|
|
46
|
+
END IF;
|
|
47
|
+
END LOOP;
|
|
48
|
+
END;
|
|
49
|
+
$$;
|