@mikara89/cap-core can emit optional, framework-neutral, best-effort
operational notifications for durable inbox and outbox transitions. Configure a
CapMessagingDiagnosticsPort when constructing CapEngine, or pass the same
object as diagnostics to CapModule.forRoot, forRootAsync, or
forInMemory.
import {
type CapMessagingDiagnosticsPort,
CapEngine,
} from '@mikara89/cap-core';
const diagnostics: CapMessagingDiagnosticsPort = {
emit(event) {
console.log(event.type, event.id, event.at);
},
};
const engine = new CapEngine({
publishStorage,
receivedStorage,
publisher,
subscriber,
diagnostics,
});
The port is optional. CAP messaging works normally when it is not configured.
The core has no dependency on NestJS, a transport, an ORM, a logging framework,
OpenTelemetry, or Node’s diagnostics_channel.
CAP messaging diagnostics intentionally exclude message payloads and headers by default. Events contain only operational metadata and normalized error text. This makes the default events suitable for typical logging, tracing, and monitoring sinks without copying business data, credentials, or authorization values. This release has no option to enable payload or header capture.
Every event has type, id, topic, at (an ISO-8601 UTC timestamp), and
retryCount. Inbox events additionally have direction: 'inbox', group, and
messageId; outbox events have direction: 'outbox'.
| Event | Extra fields | Emitted after |
|---|---|---|
inbox.processed |
— | markProcessed() succeeds |
inbox.failed |
error, nextRetryAt |
markReceivedFailed() stores a retryable failure |
inbox.dead_lettered |
error, nextRetryAt: null |
markReceivedFailed() stores a terminal failure |
inbox.retried |
reason: 'failed' \| 'stale_pending' |
the scheduler begins a registered handler invocation |
inbox.manually_requeued |
optional previousStatus |
a durable inbox requeue succeeds |
outbox.published |
— | markPublished() succeeds |
outbox.failed |
error, nextRetryAt |
markPublishFailed() stores a retryable failure |
outbox.dead_lettered |
error, nextRetryAt: null |
markPublishFailed() stores a terminal failure |
outbox.retried |
— | a claimed scheduler row with retryCount > 0 begins broker work |
outbox.manually_requeued |
optional previousStatus |
a durable outbox requeue succeeds |
Manual-requeue events use immutable identity metadata whose capture begins
before the guarded requeue mutation and always report retryCount: 0, the
durable post-requeue value. Storage adapters that expose CAP messaging
administration therefore also provide the corresponding findReceivedById() or
findPublishById() lookup. The metadata lookup is observational and does not
delay the requeue result; eligibility remains exclusively decided by the
guarded durable requeue update.
Failure retry counts are the count after the durable failure transition.
error is CAP’s normalized error string, never the original error object or a
stack trace. Transition timestamps reuse the corresponding processing,
failure, publish, requeue, or scheduler-attempt clock value.
inbox.retried is not emitted for a missing registered handler or when the
scheduler is disabled. A stale pending row is reported as stale_pending; due
failed rows, including manually requeued inbox rows, are reported as failed.
Outbox claim changes status to processing, so an outbox retry is emitted only
when its existing retryCount proves a prior attempt. Manual outbox requeue
resets that count to zero: it can therefore be followed by outbox.published
without an outbox.retried event.
Diagnostics are best-effort operational notifications, not a second message bus or a durable audit log. They provide no persistence, replay, exactly-once delivery, cross-sink ordering, process-termination delivery, or transactional consistency guarantee. Use durable storage or dedicated audit infrastructure when those guarantees are required.
CAP does not await an asynchronous sink on the messaging path. A slow sink cannot delay broker publishing, subscriber completion, scheduler progression, or manual requeue completion. A synchronous throw or returned rejected promise is logged through the configured CAP logger and swallowed. It cannot change message state, retry/dead-letter behavior, broker settlement, or a requeue result.