pgbus 0.6.8 → 0.7.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/README.md +166 -0
- data/lib/generators/pgbus/add_failed_events_index_generator.rb +4 -11
- data/lib/generators/pgbus/add_job_locks_generator.rb +4 -11
- data/lib/generators/pgbus/add_job_stats_generator.rb +4 -11
- data/lib/generators/pgbus/add_job_stats_latency_generator.rb +4 -11
- data/lib/generators/pgbus/add_job_stats_queue_index_generator.rb +4 -11
- data/lib/generators/pgbus/add_outbox_generator.rb +4 -11
- data/lib/generators/pgbus/add_presence_generator.rb +4 -11
- data/lib/generators/pgbus/add_queue_states_generator.rb +4 -11
- data/lib/generators/pgbus/add_recurring_generator.rb +4 -11
- data/lib/generators/pgbus/add_stream_stats_generator.rb +4 -11
- data/lib/generators/pgbus/install_generator.rb +4 -11
- data/lib/generators/pgbus/migrate_job_locks_generator.rb +4 -11
- data/lib/generators/pgbus/migration_path.rb +28 -0
- data/lib/generators/pgbus/tune_autovacuum_generator.rb +4 -11
- data/lib/generators/pgbus/upgrade_pgmq_generator.rb +4 -11
- data/lib/pgbus/active_job/executor.rb +3 -1
- data/lib/pgbus/circuit_breaker.rb +1 -1
- data/lib/pgbus/client.rb +10 -3
- data/lib/pgbus/configuration.rb +22 -0
- data/lib/pgbus/engine.rb +1 -0
- data/lib/pgbus/error_reporter.rb +48 -0
- data/lib/pgbus/failed_event_recorder.rb +1 -8
- data/lib/pgbus/log_formatter.rb +96 -0
- data/lib/pgbus/outbox/poller.rb +4 -4
- data/lib/pgbus/process/consumer.rb +5 -1
- data/lib/pgbus/process/dispatcher.rb +1 -1
- data/lib/pgbus/process/supervisor.rb +6 -6
- data/lib/pgbus/process/worker.rb +8 -3
- data/lib/pgbus/queue_name_validator.rb +28 -9
- data/lib/pgbus/streams/key.rb +173 -0
- data/lib/pgbus/streams/streamable.rb +57 -0
- data/lib/pgbus/streams.rb +37 -0
- data/lib/pgbus/version.rb +1 -1
- data/lib/pgbus.rb +14 -0
- data/lib/tasks/pgbus_autovacuum.rake +40 -0
- metadata +7 -1
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "digest"
|
|
4
|
+
|
|
5
|
+
module Pgbus
|
|
6
|
+
module Streams
|
|
7
|
+
# Short, pgbus-safe stream identifiers.
|
|
8
|
+
#
|
|
9
|
+
# PGMQ queue names are bounded by two ceilings: PostgreSQL's
|
|
10
|
+
# NAMEDATALEN (63 chars for `pgmq.q_<name>`) and pgmq-ruby's own
|
|
11
|
+
# stricter runtime check (`length >= 48` in
|
|
12
|
+
# `PGMQ::Client#validate_queue_name!`). The effective budget is the
|
|
13
|
+
# lower of the two, exposed as `QueueNameValidator::MAX_QUEUE_NAME_LENGTH`
|
|
14
|
+
# (currently 47). Any stream name composed from UUID primary keys
|
|
15
|
+
# and turbo-rails-style dom ids blows past that budget almost
|
|
16
|
+
# immediately:
|
|
17
|
+
#
|
|
18
|
+
# "gid://app/Ai::Chat/9c14e8b2-94c3-4c6f-8ca1-f50d2f5e22ca:messages"
|
|
19
|
+
# # => 63 chars, already too long before the "pgbus_" prefix is added.
|
|
20
|
+
#
|
|
21
|
+
# `stream_key` produces a deterministic short form suitable as a
|
|
22
|
+
# pgbus stream identifier. It normalizes each part, joins with ":",
|
|
23
|
+
# and enforces the queue-name budget (derived from the configured
|
|
24
|
+
# `queue_prefix`) at the call site — raising ArgumentError rather
|
|
25
|
+
# than letting the failure surface as an opaque QueueNameValidator
|
|
26
|
+
# error deep inside `Pgbus.stream(...).broadcast(...)`.
|
|
27
|
+
#
|
|
28
|
+
# Silent truncation is intentionally NOT supported: trimming a
|
|
29
|
+
# too-long key to fit would reintroduce the collision risk that the
|
|
30
|
+
# 64-bit digest is chosen to eliminate. Callers who overflow should
|
|
31
|
+
# shorten their own identifiers or adopt `Pgbus::Streams::Streamable`
|
|
32
|
+
# on their ActiveRecord models.
|
|
33
|
+
#
|
|
34
|
+
# Usage:
|
|
35
|
+
#
|
|
36
|
+
# Pgbus.stream_key(chat, :messages)
|
|
37
|
+
# # => "ai_chat_3a4f9c21b7d20e18:messages"
|
|
38
|
+
#
|
|
39
|
+
# Pgbus.stream_key([user, :notifications])
|
|
40
|
+
# # => "user_5fa83c91d44a2701:notifications"
|
|
41
|
+
#
|
|
42
|
+
# Pgbus.stream(Pgbus.stream_key(chat, :messages)).broadcast("<turbo-stream/>")
|
|
43
|
+
#
|
|
44
|
+
# Collision horizon: the 64-bit SHA-256 prefix gives a birthday bound
|
|
45
|
+
# of roughly 5 billion records per model class before a 50% chance of
|
|
46
|
+
# collision. For multi-tenant apps where a collision would mean two
|
|
47
|
+
# records share a stream (and receive each other's broadcasts), this
|
|
48
|
+
# is wide enough in practice. Callers with higher sensitivity can
|
|
49
|
+
# pass `digest_bits: 128`.
|
|
50
|
+
module Key
|
|
51
|
+
DEFAULT_DIGEST_BITS = 64
|
|
52
|
+
|
|
53
|
+
module_function
|
|
54
|
+
|
|
55
|
+
# Compose a short pgbus-safe stream name from any mix of records,
|
|
56
|
+
# strings, symbols, and arrays. Returns the joined key when it fits
|
|
57
|
+
# the pgbus queue-name budget; raises ArgumentError otherwise.
|
|
58
|
+
#
|
|
59
|
+
# Fragments must not contain `:` — it's the join separator, so
|
|
60
|
+
# `stream_key("a:b", :c)` and `stream_key("a", "b:c")` would both
|
|
61
|
+
# produce `"a:b:c"` and collapse two logically distinct streams
|
|
62
|
+
# onto one queue. Colons inside fragments (typically from a
|
|
63
|
+
# `to_stream_key`/`to_gid_param` implementation that forgot to
|
|
64
|
+
# sanitize) raise an ArgumentError at the call site.
|
|
65
|
+
def stream_key(*parts, digest_bits: DEFAULT_DIGEST_BITS)
|
|
66
|
+
fragments = Array(parts).flatten.map { |part| normalize(part, digest_bits: digest_bits) }
|
|
67
|
+
fragments.each { |fragment| reject_colons!(fragment) }
|
|
68
|
+
key = fragments.join(":")
|
|
69
|
+
budget = queue_name_budget
|
|
70
|
+
return key if key.length <= budget
|
|
71
|
+
|
|
72
|
+
raise ArgumentError,
|
|
73
|
+
"stream_key #{key.inspect} is #{key.length} chars, " \
|
|
74
|
+
"exceeds pgbus budget of #{budget} " \
|
|
75
|
+
"(queue_prefix=#{Pgbus.configuration.queue_prefix.inspect}, " \
|
|
76
|
+
"pgbus_max_queue_name_length=#{QueueNameValidator::MAX_QUEUE_NAME_LENGTH}). " \
|
|
77
|
+
"Shorten the streamables or use Pgbus::Streams::Streamable on the model."
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# 64-bit (default) SHA-256 prefix of the record's primary key. Stdlib
|
|
81
|
+
# only, deterministic, and fixed-length. CRC32's 32-bit output is
|
|
82
|
+
# intentionally not used here: its ~77k-row birthday bound is too
|
|
83
|
+
# tight for a multi-tenant stream identifier where a collision would
|
|
84
|
+
# route two records' broadcasts to the same queue.
|
|
85
|
+
# Full output size of the backing digest, in bits. Capping
|
|
86
|
+
# digest_bits here matters because `SHA256.hexdigest` only
|
|
87
|
+
# produces 64 hex chars (256 bits) no matter what — slicing
|
|
88
|
+
# `[0, 128]` just returns all 64 chars — so a caller asking for
|
|
89
|
+
# `digest_bits: 512` would silently get the same output as
|
|
90
|
+
# `digest_bits: 256` and walk away believing they'd widened the
|
|
91
|
+
# collision horizon. Raise instead.
|
|
92
|
+
MAX_DIGEST_BITS = ::Digest::SHA256.new.digest_length * 8 # => 256
|
|
93
|
+
|
|
94
|
+
def short_id(record, digest_bits: DEFAULT_DIGEST_BITS)
|
|
95
|
+
unless digest_bits.is_a?(Integer) && digest_bits.positive? &&
|
|
96
|
+
(digest_bits % 4).zero? && digest_bits <= MAX_DIGEST_BITS
|
|
97
|
+
raise ArgumentError,
|
|
98
|
+
"digest_bits must be a positive multiple of 4 and <= #{MAX_DIGEST_BITS} " \
|
|
99
|
+
"(SHA-256 produces #{MAX_DIGEST_BITS} bits; asking for more would silently truncate)"
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Unpersisted records all share id=nil, which hashes to a single
|
|
103
|
+
# constant digest and would collapse every new instance of the
|
|
104
|
+
# same class into one stream. Fail loud at the first unsaved
|
|
105
|
+
# call site — the whole point of the 64-bit digest is to
|
|
106
|
+
# eliminate collisions, so silently producing a shared key here
|
|
107
|
+
# would reintroduce exactly what it was chosen to prevent.
|
|
108
|
+
if record.id.nil?
|
|
109
|
+
raise ArgumentError,
|
|
110
|
+
"#{record.class.name} must be persisted before generating a stream key " \
|
|
111
|
+
"(record.id is nil — all unsaved records would collide on one stream)"
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
hex_chars = digest_bits / 4
|
|
115
|
+
::Digest::SHA256.hexdigest(record.id.to_s)[0, hex_chars]
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# Normalize a single streamable fragment to a pgbus-safe string.
|
|
119
|
+
# Mirrors the shape accepted by Turbo::Streams::StreamName and
|
|
120
|
+
# Pgbus::Streams::Stream.name_from so the two code paths agree
|
|
121
|
+
# on the wire format.
|
|
122
|
+
#
|
|
123
|
+
# - Strings and symbols pass through verbatim.
|
|
124
|
+
# - ActiveRecord models become "<param_key>_<short_id>".
|
|
125
|
+
# - Anything else responding to `to_gid_param` / `to_param` falls
|
|
126
|
+
# back to that; a UUID primary key would still overflow, which
|
|
127
|
+
# is why AR models are hashed above.
|
|
128
|
+
def normalize(part, digest_bits: DEFAULT_DIGEST_BITS)
|
|
129
|
+
case part
|
|
130
|
+
when String, Symbol
|
|
131
|
+
part.to_s
|
|
132
|
+
else
|
|
133
|
+
if defined?(::ActiveRecord::Base) && part.is_a?(::ActiveRecord::Base)
|
|
134
|
+
"#{part.class.model_name.param_key}_#{short_id(part, digest_bits: digest_bits)}"
|
|
135
|
+
elsif part.respond_to?(:to_stream_key)
|
|
136
|
+
part.to_stream_key
|
|
137
|
+
elsif part.respond_to?(:to_gid_param)
|
|
138
|
+
part.to_gid_param
|
|
139
|
+
elsif part.respond_to?(:to_param)
|
|
140
|
+
part.to_param
|
|
141
|
+
else
|
|
142
|
+
part.to_s
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
# Budget = effective pgbus queue-name limit - "<queue_prefix>_"
|
|
148
|
+
# length. Computed at call time (not a constant) so apps that
|
|
149
|
+
# override `config.queue_prefix` get the correct budget
|
|
150
|
+
# automatically.
|
|
151
|
+
def queue_name_budget
|
|
152
|
+
QueueNameValidator::MAX_QUEUE_NAME_LENGTH -
|
|
153
|
+
Pgbus.configuration.queue_prefix.length - 1
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
# Raises if a normalized fragment contains the `:` separator.
|
|
157
|
+
# Kept private-ish via module_function so the guard is shared
|
|
158
|
+
# between stream_key and any future composer without becoming
|
|
159
|
+
# part of the public surface.
|
|
160
|
+
def reject_colons!(fragment)
|
|
161
|
+
return unless fragment.include?(":")
|
|
162
|
+
|
|
163
|
+
raise ArgumentError,
|
|
164
|
+
"stream_key fragment #{fragment.inspect} contains ':' which is the " \
|
|
165
|
+
"join separator — two calls with different colon placements would " \
|
|
166
|
+
"collapse to the same key (e.g. stream_key('a:b', :c) vs " \
|
|
167
|
+
"stream_key('a', 'b:c') both produce 'a:b:c'). Strip or replace " \
|
|
168
|
+
"colons in the offending streamable before calling stream_key."
|
|
169
|
+
end
|
|
170
|
+
private_class_method :reject_colons!
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pgbus
|
|
4
|
+
module Streams
|
|
5
|
+
# ActiveRecord concern that adds `short_id` and `to_stream_key`
|
|
6
|
+
# instance methods for producing pgbus-safe stream identifiers from
|
|
7
|
+
# records whose primary key is a UUID (or any other long string).
|
|
8
|
+
#
|
|
9
|
+
# Intended for inclusion in `ApplicationRecord`:
|
|
10
|
+
#
|
|
11
|
+
# class ApplicationRecord < ActiveRecord::Base
|
|
12
|
+
# primary_abstract_class
|
|
13
|
+
# include Pgbus::Streams::Streamable
|
|
14
|
+
# end
|
|
15
|
+
#
|
|
16
|
+
# Every subclass then gets:
|
|
17
|
+
#
|
|
18
|
+
# chat.short_id
|
|
19
|
+
# # => "3a4f9c21b7d20e18"
|
|
20
|
+
#
|
|
21
|
+
# chat.to_stream_key
|
|
22
|
+
# # => "ai_chat_3a4f9c21b7d20e18"
|
|
23
|
+
#
|
|
24
|
+
# Pgbus.stream_key(chat, :messages)
|
|
25
|
+
# # => "ai_chat_3a4f9c21b7d20e18:messages"
|
|
26
|
+
#
|
|
27
|
+
# The mixin is intentionally thin: it delegates to `Pgbus::Streams::Key`
|
|
28
|
+
# so the digest policy lives in one place.
|
|
29
|
+
#
|
|
30
|
+
# `#to_stream_key` calls `Key.short_id(self)` directly rather than
|
|
31
|
+
# dispatching through `#short_id`. Ruby does NOT warn when a class
|
|
32
|
+
# defines an instance method and a later `include` adds a module
|
|
33
|
+
# with the same name — the class method silently wins. A host app
|
|
34
|
+
# that already defines its own `#short_id` (returning, say, a
|
|
35
|
+
# display-friendly abbreviation) would therefore hijack
|
|
36
|
+
# `to_stream_key` without any indication, producing stream keys
|
|
37
|
+
# the wire format never promised. Calling `Key.short_id(self)`
|
|
38
|
+
# explicitly bypasses instance-method lookup and guarantees the
|
|
39
|
+
# advertised digest regardless of what the host class does with
|
|
40
|
+
# the unqualified name.
|
|
41
|
+
module Streamable
|
|
42
|
+
# Returns a short SHA-256 prefix (64 bits / 16 hex chars by default)
|
|
43
|
+
# of this record's primary key. See `Pgbus::Streams::Key.short_id`
|
|
44
|
+
# for the digest policy and collision horizon.
|
|
45
|
+
def short_id(digest_bits: Key::DEFAULT_DIGEST_BITS)
|
|
46
|
+
Key.short_id(self, digest_bits: digest_bits)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Returns a stable, pgbus-safe identifier of the form
|
|
50
|
+
# `<model_key>_<short_id>` suitable for passing directly to
|
|
51
|
+
# `Pgbus.stream(...)` or composing with `Pgbus.stream_key`.
|
|
52
|
+
def to_stream_key
|
|
53
|
+
"#{self.class.model_name.param_key}_#{Key.short_id(self)}"
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
data/lib/pgbus/streams.rb
CHANGED
|
@@ -6,6 +6,15 @@ module Pgbus
|
|
|
6
6
|
# which returns a `Pgbus::Streams::Stream` providing `#broadcast`,
|
|
7
7
|
# `#current_msg_id`, and `#read_after`.
|
|
8
8
|
module Streams
|
|
9
|
+
# Raised when a composed stream name would overflow PGMQ's queue-name
|
|
10
|
+
# budget (derived from PostgreSQL's NAMEDATALEN=64, minus PGMQ's `q_`
|
|
11
|
+
# table prefix, minus the configured queue_prefix + separator).
|
|
12
|
+
#
|
|
13
|
+
# Inherits from ArgumentError so existing rescues of the underlying
|
|
14
|
+
# QueueNameValidator error keep working; callers that want to handle
|
|
15
|
+
# this specifically can rescue Pgbus::Streams::StreamNameTooLong.
|
|
16
|
+
class StreamNameTooLong < ArgumentError; end
|
|
17
|
+
|
|
9
18
|
# Process-wide registry of server-side audience filter predicates.
|
|
10
19
|
# Register filters at boot time via:
|
|
11
20
|
# Pgbus::Streams.filters.register(:admin_only) { |user| user.admin? }
|
|
@@ -30,6 +39,7 @@ module Pgbus
|
|
|
30
39
|
|
|
31
40
|
def initialize(streamables, client: Pgbus.client)
|
|
32
41
|
@name = self.class.name_from(streamables)
|
|
42
|
+
self.class.validate_name_length!(@name, streamables)
|
|
33
43
|
@client = client
|
|
34
44
|
@ensured = false
|
|
35
45
|
@ensure_mutex = Mutex.new
|
|
@@ -108,6 +118,33 @@ module Pgbus
|
|
|
108
118
|
end
|
|
109
119
|
end
|
|
110
120
|
|
|
121
|
+
# Enforces the pgbus queue-name budget at the Stream-construction
|
|
122
|
+
# boundary so a forgotten call site fails with an actionable error
|
|
123
|
+
# (pointing at the offending streamables and suggesting
|
|
124
|
+
# `Pgbus.stream_key`) instead of an opaque QueueNameValidator
|
|
125
|
+
# failure three frames deep in Client#ensure_stream_queue.
|
|
126
|
+
#
|
|
127
|
+
# The budget is computed from `config.queue_prefix` at call time
|
|
128
|
+
# so apps that override the prefix get the correct limit. Does not
|
|
129
|
+
# mutate the name — silent truncation is a footgun for
|
|
130
|
+
# multi-tenant apps where collisions would mix broadcasts across
|
|
131
|
+
# records. Callers who need a short, safe identifier should use
|
|
132
|
+
# `Pgbus.stream_key(...)` or include `Pgbus::Streams::Streamable`
|
|
133
|
+
# on their ActiveRecord models.
|
|
134
|
+
def self.validate_name_length!(name, streamables)
|
|
135
|
+
budget = Key.queue_name_budget
|
|
136
|
+
return if name.length <= budget
|
|
137
|
+
|
|
138
|
+
raise StreamNameTooLong,
|
|
139
|
+
"Stream name #{name.inspect} is #{name.length} chars, " \
|
|
140
|
+
"exceeds pgbus budget of #{budget} " \
|
|
141
|
+
"(queue_prefix=#{Pgbus.configuration.queue_prefix.inspect}, " \
|
|
142
|
+
"pgbus_max_queue_name_length=#{QueueNameValidator::MAX_QUEUE_NAME_LENGTH}). " \
|
|
143
|
+
"Streamables: #{streamables.inspect}. " \
|
|
144
|
+
"Use Pgbus.stream_key(*streamables) to produce a safe short name, " \
|
|
145
|
+
"or include Pgbus::Streams::Streamable on the model."
|
|
146
|
+
end
|
|
147
|
+
|
|
111
148
|
private
|
|
112
149
|
|
|
113
150
|
def ensure_queue!
|
data/lib/pgbus/version.rb
CHANGED
data/lib/pgbus.rb
CHANGED
|
@@ -105,6 +105,20 @@ module Pgbus
|
|
|
105
105
|
@stream_cache.compute_if_absent(name) { Streams::Stream.new(streamables) }
|
|
106
106
|
end
|
|
107
107
|
|
|
108
|
+
# Compose a short, pgbus-safe stream identifier from any mix of
|
|
109
|
+
# records, strings, symbols, and arrays. Delegates to
|
|
110
|
+
# `Pgbus::Streams::Key.stream_key`; raises `ArgumentError` if the
|
|
111
|
+
# resulting key would overflow the pgbus queue-name budget. See
|
|
112
|
+
# `lib/pgbus/streams/key.rb` for the digest policy and rationale.
|
|
113
|
+
#
|
|
114
|
+
# Pgbus.stream_key(chat, :messages)
|
|
115
|
+
# # => "ai_chat_3a4f9c21b7d20e18:messages"
|
|
116
|
+
#
|
|
117
|
+
# Pgbus.stream(Pgbus.stream_key(chat, :messages)).broadcast(html)
|
|
118
|
+
def stream_key(*parts, **)
|
|
119
|
+
Streams::Key.stream_key(*parts, **)
|
|
120
|
+
end
|
|
121
|
+
|
|
108
122
|
def reset!
|
|
109
123
|
@client&.close
|
|
110
124
|
@client = nil
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
namespace :pgbus do
|
|
4
|
+
desc "Apply autovacuum tuning to PGMQ queue/archive tables and high-churn pgbus tables"
|
|
5
|
+
task tune_autovacuum: :environment do
|
|
6
|
+
require "pgbus/autovacuum_tuning"
|
|
7
|
+
|
|
8
|
+
conn = Pgbus.configuration.connects_to ? Pgbus::BusRecord.connection : ActiveRecord::Base.connection
|
|
9
|
+
|
|
10
|
+
# Only run if pgmq schema exists (tables may not be created yet during
|
|
11
|
+
# initial setup — the install migration handles tuning itself).
|
|
12
|
+
pgmq_exists = conn.select_value(
|
|
13
|
+
"SELECT 1 FROM information_schema.schemata WHERE schema_name = 'pgmq'"
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
unless pgmq_exists
|
|
17
|
+
puts "[pgbus] PGMQ schema not found — skipping autovacuum tuning."
|
|
18
|
+
next
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
puts "[pgbus] Applying autovacuum tuning to PGMQ queue/archive tables..."
|
|
22
|
+
conn.execute(Pgbus::AutovacuumTuning.sql_for_all_queues)
|
|
23
|
+
|
|
24
|
+
puts "[pgbus] Applying autovacuum tuning to high-churn pgbus tables..."
|
|
25
|
+
conn.execute(Pgbus::AutovacuumTuning.sql_for_high_churn_tables)
|
|
26
|
+
|
|
27
|
+
puts "[pgbus] Autovacuum tuning complete."
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Reapply autovacuum settings after schema:load since Ruby-format schema.rb
|
|
32
|
+
# does not preserve ALTER TABLE ... SET (reloptions). This is a no-op if the
|
|
33
|
+
# tables don't exist yet (IF EXISTS guards in the SQL).
|
|
34
|
+
%w[db:schema:load db:schema:load:pgbus].each do |task_name|
|
|
35
|
+
next unless Rake::Task.task_defined?(task_name)
|
|
36
|
+
|
|
37
|
+
Rake::Task[task_name].enhance do
|
|
38
|
+
Rake::Task["pgbus:tune_autovacuum"].invoke if Rake::Task.task_defined?("pgbus:tune_autovacuum")
|
|
39
|
+
end
|
|
40
|
+
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.7.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Mikael Henriksson
|
|
@@ -215,6 +215,7 @@ files:
|
|
|
215
215
|
- lib/generators/pgbus/add_stream_stats_generator.rb
|
|
216
216
|
- lib/generators/pgbus/install_generator.rb
|
|
217
217
|
- lib/generators/pgbus/migrate_job_locks_generator.rb
|
|
218
|
+
- lib/generators/pgbus/migration_path.rb
|
|
218
219
|
- lib/generators/pgbus/templates/add_failed_events_unique_index.rb.erb
|
|
219
220
|
- lib/generators/pgbus/templates/add_job_locks.rb.erb
|
|
220
221
|
- lib/generators/pgbus/templates/add_job_stats.rb.erb
|
|
@@ -255,6 +256,7 @@ files:
|
|
|
255
256
|
- lib/pgbus/configuration/capsule_dsl.rb
|
|
256
257
|
- lib/pgbus/dedup_cache.rb
|
|
257
258
|
- lib/pgbus/engine.rb
|
|
259
|
+
- lib/pgbus/error_reporter.rb
|
|
258
260
|
- lib/pgbus/event.rb
|
|
259
261
|
- lib/pgbus/event_bus/handler.rb
|
|
260
262
|
- lib/pgbus/event_bus/publisher.rb
|
|
@@ -268,6 +270,7 @@ files:
|
|
|
268
270
|
- lib/pgbus/generators/database_target_detector.rb
|
|
269
271
|
- lib/pgbus/generators/migration_detector.rb
|
|
270
272
|
- lib/pgbus/instrumentation.rb
|
|
273
|
+
- lib/pgbus/log_formatter.rb
|
|
271
274
|
- lib/pgbus/outbox.rb
|
|
272
275
|
- lib/pgbus/outbox/poller.rb
|
|
273
276
|
- lib/pgbus/pgmq_schema.rb
|
|
@@ -298,8 +301,10 @@ files:
|
|
|
298
301
|
- lib/pgbus/streams/cursor.rb
|
|
299
302
|
- lib/pgbus/streams/envelope.rb
|
|
300
303
|
- lib/pgbus/streams/filters.rb
|
|
304
|
+
- lib/pgbus/streams/key.rb
|
|
301
305
|
- lib/pgbus/streams/presence.rb
|
|
302
306
|
- lib/pgbus/streams/signed_name.rb
|
|
307
|
+
- lib/pgbus/streams/streamable.rb
|
|
303
308
|
- lib/pgbus/streams/turbo_broadcastable.rb
|
|
304
309
|
- lib/pgbus/streams/turbo_stream_override.rb
|
|
305
310
|
- lib/pgbus/streams/watermark_cache_middleware.rb
|
|
@@ -319,6 +324,7 @@ files:
|
|
|
319
324
|
- lib/pgbus/web/streamer/registry.rb
|
|
320
325
|
- lib/pgbus/web/streamer/stream_event_dispatcher.rb
|
|
321
326
|
- lib/puma/plugin/pgbus_streams.rb
|
|
327
|
+
- lib/tasks/pgbus_autovacuum.rake
|
|
322
328
|
- lib/tasks/pgbus_pgmq.rake
|
|
323
329
|
- lib/tasks/pgbus_streams.rake
|
|
324
330
|
homepage: https://github.com/mhenrixon/pgbus
|