feat(event-process): event-process consumer + wildcard subscribe for events.received.* (EVO-1208)#28
Conversation
There was a problem hiding this comment.
Sorry @nickoliveira23, you have reached your weekly rate limit of 500000 diff characters.
Please try again later or upgrade to continue using Sourcery
Code reviewed (positive) — merge blocked on a rebase after #27 landedThe review itself is done and positive:
Why it can't merge yet: #27 (EVO-1199) is merged to develop. I retargeted this PR's base from To unblock (dev): rebase
Not approving yet — this is purely a branch-state rebase, not a code change. Holding until rebase + green gate. |
20f124a to
49e8399
Compare
Review — code looks sound; merge blocked on a rebaseReviewed the consumer, both adapters' One LOW — a contract follow-up, not this PR: the consumer terminally drops any envelope failing the strict Merge blocked on a rebase: this PR now conflicts with |
…ange (EVO-1208)
Adds IMessageBroker.subscribePattern(prefix, handler): Kafka subscribes with a
native RegExp under groupId ${runMode}-${prefix} (no topic creation for the
pattern); RabbitMQ binds a durable queue to a shared <prefix> topic exchange
with the <prefix>.# binding. Aligns the RabbitMQ topic->exchange mapping for
the events.received family only (shared exchange + routing key per platform),
per the EVO-1195 contract — campaigns.* keeps the per-topic model. Closes the
EVO-1199 coverage gap with a parametrized wildcard fan-in scenario.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…received.* (EVO-1208) EventProcessModule + EventsReceivedConsumer subscribe the events.received family via subscribePattern, run each envelope under the correlation context, and ack (nack+requeue on failure); EventProcessService is the validating stub for stories 3.4-3.7. Removes EVENT_PROCESS from STUB_RUN_MODES and conditionally imports the module (AppFactory.shouldStartEventProcess()). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…otstrap (EVO-1208) Addresses self-review findings: - HIGH: a schema-invalid envelope threw and was nacked with requeue, looping forever (tight redelivery, DoS-class). Validation failures now raise a typed InvalidEnvelopeError and are dropped (terminal nack); only transient errors requeue. - MEDIUM: move the broker subscription from onModuleInit to onApplicationBootstrap so the broker adapter is guaranteed active first (hook order across modules is otherwise undefined). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…-1208) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
49e8399 to
2e7cab2
Compare
dpaes
left a comment
There was a problem hiding this comment.
Review — Approved ✅
Re-rebase confirmed clean: the 4 EVO-1208 commits replay onto current develop (0 EVO-1199 commits), and the additive conflicts were resolved correctly — provisionTopic (EVO-1200) + subscribePattern (EVO-1208) side-by-side in both adapters; app.module.ts keeps both the CampaignPackerModule (EVO-1215) and event-process registrations. Scope is unchanged from the version I reviewed (541+/11−, 14 files). The EVO-1199 contract-suite merge gate passed (deterministic contract scenarios + tenant-db-context green); only the explicitly non-blocking broker-restart reconnect scenario is still pending.
Code was already reviewed and is sound: invalid envelope → typed InvalidEnvelopeError → terminal drop while transient errors requeue (closes the round-1 infinite-redelivery HIGH); the wildcard is anchored/scoped so it can't swallow campaigns.*; subscription runs in onApplicationBootstrap after the adapter is active.
Known LOW (contract follow-up, not a blocker): the consumer terminally drops an envelope whose correlationId fails the strict z.uuidv4() schema, while the EVO-1209 producer deliberately publishes non-UUID SAFE_CORRELATION_ID tokens. External providers don't send X-Correlation-Id (common path mints a UUID and passes); fix belongs in the contract/correlation story (relax the contract to SAFE_CORRELATION_ID), NOT by weakening this consumer's terminal-drop.
Merging to develop.
Summary
Wires
RUN_MODE=event-process(story 3.3): the consumer end of the webhook event pipeline that subscribes to the wholeevents.received.<platform>topic family, propagatescorrelationId, and runs each envelope through a validating stub handler (stories 3.4–3.7 fill in the real pipeline).Resolves the wildcard-subscribe gap the family needs:
IMessageBroker.subscribePattern(prefix, handler)— Kafka subscribes with a native RegExp (^events\.received\.[^.]+$) under groupId${runMode}-${prefix}, no topic creation for the pattern; RabbitMQ binds a durable queue to a sharedevents.receivedtopic exchange with theevents.received.#binding.events.receivedfamily only (shared exchange + routing key per platform), per the EVO-1195 contract (EVENTS_RECEIVED_RABBITMQ_BINDING).campaigns.*keeps the per-topic model — proven unchanged by the existing contract scenarios.Stacked PR
Based on
feat/EVO-1199(PR #27, in review) because it editsbroker.contract.spec.ts, which is not yet ondevelop. Retarget the base todeveloponce #27 merges. The EVO-1208 delta is the 13 files below.Security
terminal_failuresmetric) instead of requeued — prevents an infinite redelivery loop on a poison message. Only transient errors requeue.Test plan
evo-flow: npm run typecheck/npm run lint— cleanevo-flow: npm test— 62 broker + event-process unit specs pass (incl. subscribePattern, terminal-drop, bootstrap subscription). One unrelated pre-existing failure (campaigns.controller.spec, confirmed on base).evo-flow: BROKER_CONTRACT=1 npm run test:contract— 14/14 deterministic scenarios incl. wildcard fan-in, both adapters, against the CI broker stackevo-flow: RUN_MODE=event-process npm run dev— boot smoke:EventProcessModuleloads, broker boots, consumer subscribes ononApplicationBootstrap, no crash on cold start (zero topics)Changed Files
src/shared/broker/interfaces/message-broker.interface.tssrc/shared/broker/adapters/{kafka,rabbitmq}-broker.adapter.ts(+ specs)src/shared/broker/broker.contract.spec.tssrc/runners/event-process/event-process.module.tssrc/runners/event-process/services/{event-process.service,events-received.consumer}.ts(+ specs)src/main.ts,src/app.module.ts,src/bootstrap/bootstrap.service.tsNotes (out of scope, not blocking)
metadataMaxAge) — a cold event-process may lag a first-ever platform topic by minutes. Mitigated once EVO-1200 [1.7] pre-provisions the topics.attachConsumerpath; no dedicated reconnect test.Linked Issue
🤖 Generated with Claude Code