chore: version packages#215
Open
connectum-release-bot[bot] wants to merge 1 commit into
Open
Conversation
@connectum/auth
@connectum/cli
@connectum/core
@connectum/events
@connectum/events-amqp
@connectum/events-kafka
@connectum/events-nats
@connectum/events-redis
@connectum/healthcheck
@connectum/interceptors
@connectum/otel
@connectum/protoc-gen-catalog
@connectum/reflection
@connectum/test-fixtures
@connectum/testing
commit: |
connectum-release-bot
Bot
force-pushed
the
changeset-release/main
branch
9 times, most recently
from
July 5, 2026 22:11
8fd8dc3 to
222c024
Compare
connectum-release-bot
Bot
force-pushed
the
changeset-release/main
branch
from
July 6, 2026 03:02
222c024 to
e8967cd
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Highlights
publishRetryon@connectum/events-amqpauto-retries connection-class publish failures (never nacks/timeouts) with bounded backoff and honest at-least-once semantics (#222), and the newdrainPublishTimeouton@connectum/eventsgives in-flight publishes a bounded drain window duringstop()(#220).initialConnectMaxRetriesbounds the first connect (#219), andtreatTopologyErrorAsFatalstops infinite recovery on deterministic topology drift (404/406) at runtime, mirroring the 1.2.0 startup fail-fast (#218).onLifecyclecallback delivers the full connection-lifecycle event union in guaranteed order (#216), andAmqpTopologyErrornow carries a machine-readable.objectidentifying the failing exchange/queue/binding (#217).@connectum/events-amqp/testingsubpath ships a programmableFakeAmqpAdapter: FIFO publish outcomes with the real typed errors, a deterministic recovery control surface, and delivery with settlement counts (#224).@connectum/eventsexports theEventAdapterFactorytype for per-consumer adapter wiring and test seams (#223).Repo-wide changes
These changeset entries appear identically across multiple packages and are listed once.
#214
e2b613bThanks @intech! - docs: recovery backoff tuning and publisher shutdown guidanceAmqpRecoveryOptionsJSDoc — the amqplib v2 strategy is symmetric jitter around the exponential base (not equal-jitter), with the cap applied before jitter (hence the overshoot abovemaxDelay). Documented the exact full-jitter workaround (jitter: 1+ halvedinitialDelay/maxDelay→ delay uniform in[0, intended cap], verified against amqplib 2.0.1) with a fragility caveat and upstream tracking links (recovery: allow a custom delay strategy (calculateDelay option) amqp-node/amqplib#855, recovery: separate retry budget for the initial connect amqp-node/amqplib#856).stop()drains consumer handlers only; await-before-stop recipe for at-least-once producers; the stopping-gate limitation for publishes from draining handlers (#212); the planned opt-indrainPublishTimeout(#196).Affects: @connectum/events, @connectum/events-amqp (2 packages).
Package changes
@connectum/events@1.3.0
Minor
#223
774ef46Thanks @intech! - feat: namedEventAdapterFactorytype + official DI/testing guidance (#204)EventAdapterFactory(() => EventAdapter) — the previously inline factory shape ofcreateBroadcastSubscribers'adapteroption, now a named public type (per-adapter named types are deliberately not added).EventAdapterinstance at the composition root (a configured test double does not fit a zero-argument factory without a wrapper); the factory is the secondary pattern for per-consumer connections (broadcast reactors). Test-double guidance:MemoryAdapterfor the generic happy path; broker-specific failure semantics via the upcoming@connectum/events-amqp/testingfake (#203).#220
8962afaThanks @intech! - feat:drainPublishTimeout— opt-in symmetric publish drain on shutdown (#196)EventBusOptions.drainPublishTimeout: duringstop(), wait up to the budget for in-flightpublish()promises (started beforestop()) to settle, before the adapter disconnects and would fail their confirms. Bus-level (L1): zero adapter-contract changes — nats/kafka/redis/amqp get the drain for free.drainTimeout) — shutdown waits for the slower of the two budgets, never their sum.unhandledRejection; the caller's ownpublish()promise is unaffected.undefined(and0/negative) — disabled:stop()behavior stays bit-for-bit (pinned by a regression test).@connectum/events-amqp@1.3.0
Minor
#222
3a76225Thanks @intech! - feat:publishRetry— opt-in bounded publish retry for connection-class outcomes (#195)publishRetry: boolean | AmqpPublishRetryOptions: apublish()failing withAmqpConnectionError(publish during a recovery window; in-flight confirm lost to a drop) retries in place — a short broker blip becomes a transparent delay instead of an instant rejection. Backoff mirrors the recovery formula;maxRetriesdefaults to a bounded5.AmqpPublishTimeoutErrorjoins only viaretryOnTimeout: true.isAutoRetriablePublishError— deliberately narrower than the at-least-once republish matrix (a broker nack is republish-safe by policy but never auto-retried inline; deterministic outcomes never retry). Docs distinguish the two boundaries explicitly.x-event-id/messageIdstay stable across attempts (incl.externalContract) as the consumer-side dedup anchor.disconnect()(interruptible backoff) and lives inside theadapter.publish()promise, so the bus-leveldrainPublishTimeoutcovers retries automatically. Under single-flight correlation, retries hold the chain (ordering preserved; head-of-line blocking documented). The publish channel is re-resolved per attempt.#216
82f2c29Thanks @intech! - feat: discriminatedonLifecycleconnection-lifecycle callback (#197)lifecycle.onLifecycle(event)— a single discriminated union (type:connected|disconnected|reconnecting|reconnect-failed|setup-failed|blocked|unblocked) with exactly-once semantics pinned by integration tests.connectedcarriesreconnected: boolean;blocked/unblockedsurface RabbitMQ flow control (connection.blocked) for the first time. Scope: per-retry events of the initial connect loop are not yet surfaced (tracked in #198).onLifecycle(likeonSetupFailed/failFastOnInitialSetupError) enables the startup validation probe — one extra short-lived connection plus a topology validation pass atconnect()(recovery enabled required) — sosetup-failed { initial: true }is delivered for a deterministic misconfiguration at boot.onConnected,onDisconnected,onReconnecting,onReconnectFailed,onSetupFailed) are now a compatibility shim over the union and are@deprecatedsince 1.3.0 (removal not before 2.0). When both are set, flat callbacks fire afteronLifecycle.onDisconnectedtwice — once via the raw connectionerrorre-emit and once via the recoverydisconnectevent; it now fires exactly once per drop on both surfaces. Disconnect-counter metrics of existing consumers will roughly halve. A graceful server close was and remains single-fire.recovery: falsemode):disconnectedis now delivered once per connection loss on the connectionclose(with the precedingerrorkept as the cause) — including a server-forced graceful close, which previously surfaced no event at all. The adapter's owndisconnect()and a failed-setup discard do not emit it.errorlistener (a broker drop during the probe window could previously crash the process via an unhandlederrorevent); a stale reconnect-attempt counter no longer leaks into a laterconnect()incarnation.#219
d21e3c8Thanks @intech! - feat:initialConnectMaxRetries— bounded, observable initial connect (#198)recovery.initialConnectMaxRetries(N retries = N+1 attempts, mirroringmaxRetriessemantics): expresses "bounded startup, unbounded steady-state", which a singlemaxRetriescannot (its counter resets on every success). Default unset — behavior unchanged.connect()with a typedAmqpConnectionErrorafter a terminalreconnect-failed— never a silent block.reconnecting { attempt, delay },setup-failed { initial: true, attempt }) — previously the initial retry loop ran inside amqplib before any wiring could attach and was silent. This closes the documented scope gap from theonLifecycle/treatTopologyErrorAsFatalreleases.failFastOnInitialSetupErrorstill short-circuits deterministic topology errors immediately; the backoff sleep is interruptible bydisconnect().#217
f0e9040Thanks @intech! - feat: machine-readableobjectonAmqpTopologyError(#202)AmqpTopologyObjectdiscriminated union —{ kind: 'exchange' | 'queue', name }or{ kind: 'binding', source, destination, destinationType, routingKey }(a binding has no name of its own) — exposed asAmqpTopologyError.objectand exported from the barrel.applyTopologycheck and assert modes per object, subscribe-path queue declaration/bindings/check-mode verification, consume failures), so CI drift checks and observability never parse broker-reply text.object.kindsays what was being declared; why it failed stays with the error class andcause. One documented exception: the config-validation error for a malformed binding declaration (neitherqueuenorexchangeset) carries noobject— its destination is exactly the missing piece.AmqpTopologyErrorconstructor now takes an options-bag{ cause?, object? }. Construction stays bit-for-bit compatible: message-only instances install no owncause/objectkeys (pinned by unit tests), so spread clones and own-property log serializers see no new keys unless an object is actually supplied.#218
24e73f6Thanks @intech! - feat:treatTopologyErrorAsFatal— stop recovery on deterministic topology drift (#201)setup-failedthen the terminalreconnect-failedlifecycle event, and subsequent publishes fail fast withAmqpConnectionError.404NOT_FOUND /406PRECONDITION_FAILED are deterministic; transient causes wrapped intoAmqpTopologyErrorduring a setup pass (320connection-forced,541internal-error,405resource-locked, mid-setup connection drops) stay in normal recovery.instanceof AmqpTopologyErroralone is deliberately NOT the gate. The RabbitMQ cluster classic-queue outage 404 ("home node ... down or inaccessible") is explicitly excluded as transient.connect-failedhandler, before amqplib schedules the next retry; subscription records are cleared (consumers are dead; a laterconnect()starts from a clean slate — pinned by a reconnect-after-fatal integration test). A fatal classification racing the adapter's owndisconnect()is suppressed (no terminal events after a graceful stop began).subscribe()parked in the recovering wrapper's waiter queue when the cycle dies now rejects with the typedAmqpConnectionError(was amqplib's plainError("Connection closed")).failFastOnInitialSetupError's job. Setting both covers boot and steady state; the remaining gap (broker unreachable atconnect()with drift surfacing before the first successful connect) is covered by neither flag until #198. Defaultfalse— behavior unchanged unless opted in.#224
ddc9ec7Thanks @intech! - feat: programmableFakeAmqpAdaptertest double via@connectum/events-amqp/testing(#203)@connectum/events-amqp/testingwithFakeAmqpAdapter— model AMQP failure semantics in unit tests without a broker: FIFO publish outcomes (control.nextPublishwith the real typed error classes, incl.AmqpPublishTimeoutError— the state-UNKNOWN outcome no real broker reproduces deterministically), deterministic connection lifecycle (dropConnection/completeRecovery/exhaustRecovery/failSetup/block), wildcard + competing-consumer delivery with a settlement result ({ delivered, acked, nacked, requeued, failed }), and apublishedrecord of bus-facing publishes.already connectedfrom live/recovering/retries-exhausted states; mid-recoverysubscribe()parks and settles with the recovery outcome;setup-failed/fail-fast gate onAmqpTopologyErrorlike the real probe); incoming envelope headers honored and stripped like the real consumer; handler rejections swallowed like the real nack-on-error path;instanceofholds across the subpath boundary (tsupsplitting: true— shared error-class chunk, pinned by a dist-level test).amqplibnornode:testinto the consumer graph (only@connectum/events+node:crypto).attempt + 1to model redelivery); no wire-level envelope onpublished; report-and-proceed on a non-fail-fast startup setup failure.