pgbus 0.15.0 → 0.15.1
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 +4 -0
- data/README.md +1 -1
- data/lib/pgbus/current_attributes.rb +27 -3
- data/lib/pgbus/version.rb +1 -1
- 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: c419d130102e92e1bd355df6e98211e44eeead76298f9ce58bd6c285b1de24a9
|
|
4
|
+
data.tar.gz: dab0eefe9c7a23aee676b928521841adffb6d38f084993c6bb3ab56f9ade207f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d8cedff08ffed91f3b9a9c1b9df1b2147790ec9bf7e5117b22a4af19b865b239df4883d6708153ec2efc9de5207e007cb4d2cfd06440ac3b4bd25e63d1eea369
|
|
7
|
+
data.tar.gz: fcb2ec48f7daf53dc46d5c388cb3b4e1acd99a568e74e92253736efb8ba4bc52fd9704d287fbaafcea893d063676b3f68ceac3d82b79fc3906ef4d7bbc43dcd3
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
### Fixed
|
|
4
|
+
|
|
5
|
+
- **`current_attributes` capture skips an unpersisted record instead of raising at enqueue (issue #435).** An attribute holding an Active Record instance with no id — a dev-mode fallback record assigned to `Current`, a form-built model captured before `save`, a destroyed record whose locate is guaranteed to fail — made every `perform_later` in that context raise `Pgbus::CurrentAttributesError`, even though such a record can never round-trip (no id → no GlobalID) and capture is ambient: the enqueuer never opted into persisting that attribute per-call, so its momentary state must not abort the enqueue. `capture` now skips any attribute value that answers `persisted?` falsey (so destroyed-but-id-bearing records are skipped too, not just `new_record?`) with a debug log naming the class, attribute and why; the rest of the class's attributes still persist. The `except:` guidance and the loud `CurrentAttributesError` remain for genuinely unserializable values — objects without the Active Record duck-type (`respond_to?(:persisted?)`) are untouched. Applies to jobs and event-bus publish alike (same capture path). Refs #435.
|
|
6
|
+
|
|
3
7
|
### Added
|
|
4
8
|
|
|
5
9
|
- **First-class `Current` support: ActiveSupport::CurrentAttributes persist across enqueue → perform (issue #430).** The executor already reset `CurrentAttributes` around every job (so nothing leaked) but nothing restored it — `Current.tenant` was always nil inside a job. New `config.current_attributes` (`nil` = off; `:auto` = every `ActiveSupport::CurrentAttributes` subclass; an Array of classes/names; or a Hash of class => `{ only: [...] }` / `{ except: [...] }`). The new `Pgbus::ActiveJob::CurrentAttributes` mixin (included on `ActiveJob::Base` by the engine next to `BatchId`) captures the assigned attributes of each persisted class in `serialize` — serialized with `ActiveJob::Arguments`, so records become GlobalIDs and fall under the `allowed_global_id_models` allowlist on the way back — under the job-hash key `pgbus_current`, and restores them by wrapping the **whole** `perform_now` in nested `Current.set`, so `before_perform`, `perform`, `rescue_from`, `retry_on` / `discard_on` blocks and jobs enqueued from inside `perform` all see the context, under the pgbus worker and Rails' `:test` / `:inline` adapters alike. A deserialized job re-serializes the context it was enqueued with, so a `retry_on` re-enqueue keeps the original; concurrency-blocked promotion, dead-letter / dashboard retry and `perform_all_later` carry it by construction. An unserializable attribute raises `Pgbus::CurrentAttributesError` at `perform_later` naming the class, attribute and the `except:` fix — nothing is dropped silently; a class that no longer exists or an attribute no longer defined is skipped with a log line (Sidekiq parity). Per job class: `self.pgbus_persist_current_attributes = false` or a spec override. Unconfigured installs have byte-identical payloads. Dashboard: failed-job and dead-letter detail pages gain a **Context** card (`Pgbus::Web::JobContext`, through `PayloadFilter`). Event bus follows in #431. Refs #430.
|
data/README.md
CHANGED
|
@@ -674,7 +674,7 @@ end
|
|
|
674
674
|
|
|
675
675
|
Events get the same hop: `Pgbus.publish` captures `Current` into the event envelope and the consumer restores it around every `handle` — including across the transactional outbox (captured at `Outbox.publish_event`, inside your transaction). Handlers can also read the raw form via `event.context`.
|
|
676
676
|
|
|
677
|
-
Captured at enqueue via `ActiveJob::Arguments` (records become GlobalIDs, gated by `allowed_global_id_models`), preserved across retries, concurrency-blocked promotion, dead-letter retry and `perform_all_later`; an unserializable attribute raises at `perform_later` with the `except:` fix. The dashboard shows the context on failed-job and dead-letter pages. Details: [Active Job → Current attributes](https://pgbus.zoolutions.llc/docs/active-job).
|
|
677
|
+
Captured at enqueue via `ActiveJob::Arguments` (records become GlobalIDs, gated by `allowed_global_id_models`), preserved across retries, concurrency-blocked promotion, dead-letter retry and `perform_all_later`; an unserializable attribute raises at `perform_later` with the `except:` fix, while an **unpersisted** record (no id — it could never be restored) is skipped with a debug log instead of aborting the enqueue. The dashboard shows the context on failed-job and dead-letter pages. Details: [Active Job → Current attributes](https://pgbus.zoolutions.llc/docs/active-job).
|
|
678
678
|
|
|
679
679
|
### Consumer priority
|
|
680
680
|
|
|
@@ -8,8 +8,11 @@ module Pgbus
|
|
|
8
8
|
# (config.current_attributes: :auto, an explicit list, or per-class
|
|
9
9
|
# only:/except: filters) serialized through ActiveJob::Arguments — so
|
|
10
10
|
# GlobalID models, Symbols, Times round-trip like job arguments and fall
|
|
11
|
-
# under the allowed_global_id_models allowlist on the way back.
|
|
12
|
-
#
|
|
11
|
+
# under the allowed_global_id_models allowlist on the way back. An
|
|
12
|
+
# attribute holding an unpersisted record is skipped with a debug log
|
|
13
|
+
# (no id → no GlobalID → it could never be restored; see
|
|
14
|
+
# #reject_unpersisted). `restore` nests `klass.set(attrs)` for the
|
|
15
|
+
# duration of a block.
|
|
13
16
|
#
|
|
14
17
|
# The ActiveJob side (Pgbus::ActiveJob::CurrentAttributes) calls capture
|
|
15
18
|
# from `serialize` and restore around `perform_now`, so the hop works under
|
|
@@ -34,7 +37,7 @@ module Pgbus
|
|
|
34
37
|
captured = {}
|
|
35
38
|
persisted_specs(config, override: override).each do |spec|
|
|
36
39
|
klass = resolve_class(spec[:name]) or next
|
|
37
|
-
attrs = filter_attrs(klass.attributes, spec)
|
|
40
|
+
attrs = reject_unpersisted(klass, filter_attrs(klass.attributes, spec))
|
|
38
41
|
next if attrs.empty?
|
|
39
42
|
|
|
40
43
|
captured[klass.name] = serialize_attrs(klass, attrs)
|
|
@@ -126,6 +129,27 @@ module Pgbus
|
|
|
126
129
|
attrs
|
|
127
130
|
end
|
|
128
131
|
|
|
132
|
+
# An unpersisted record cannot round-trip by definition — no id, no
|
|
133
|
+
# GlobalID — and capture is ambient: the enqueuer never opted into
|
|
134
|
+
# persisting this attribute per-call, so its momentary state (a dev-mode
|
|
135
|
+
# fallback record, a form-built model assigned to Current before save,
|
|
136
|
+
# a destroyed record whose locate is guaranteed to fail) must not abort
|
|
137
|
+
# the enqueue. Skip it like an unassigned attribute. persisted? (not
|
|
138
|
+
# new_record?) so destroyed-but-id-bearing records are skipped too;
|
|
139
|
+
# objects without the Active Record duck-type pass through untouched
|
|
140
|
+
# and still hit serialize_attrs' loud CurrentAttributesError if bad.
|
|
141
|
+
def reject_unpersisted(klass, attrs)
|
|
142
|
+
attrs.reject do |name, value|
|
|
143
|
+
next false unless value.respond_to?(:persisted?) && !value.persisted?
|
|
144
|
+
|
|
145
|
+
Pgbus.logger.debug do
|
|
146
|
+
"[Pgbus] current_attributes: #{klass.name}##{name} holds an unpersisted #{value.class} — " \
|
|
147
|
+
"skipped (no id to serialize; it could never be restored)"
|
|
148
|
+
end
|
|
149
|
+
true
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
|
|
129
153
|
def serialize_attrs(klass, attrs)
|
|
130
154
|
::ActiveJob::Arguments.serialize([attrs]).first
|
|
131
155
|
rescue ::ActiveJob::SerializationError, URI::Error
|
data/lib/pgbus/version.rb
CHANGED