@logisticity/events
v4.0.0
Published
A Redis Streams event broker for TypeScript: at-least-once delivery, dead-lettering, poison handling, partitioned ordering, a batching publisher, and a consumer runtime.
Maintainers
Readme
@logisticity/events
A Redis Streams event broker library for TypeScript: reliable at-least-once delivery, dead-lettering, poison handling, partitioned ordering, a batching publisher, a consumer runtime with typed operator and metrics surfaces, and a declarative event-bus facade for quick application wiring.
This 4.x line is a clean-room re-founding of the library under the
Proofload method. Its delivery core was
rebuilt from frozen contracts with the full build record kept in
process/. If you used 3.x, treat 4.0 as a new API.
Why
The transport is built around the delivery guarantees that are easy to get wrong with Redis Streams:
- At-least-once, ack-after-effect. An entry is acked only after its handler effect completes; nothing is acked-then-processed.
- Mandatory recovery. Pending entries are reclaimed with
XAUTOCLAIMafter a min-idle window, so a dead consumer's work is picked up, not stranded. - Filtered, never stranded. An entry with no registered handler is acked and counted, never left pending.
- Dead-lettering that cannot lose. The DLQ move appends and confirms before it acks the original; a crash in between yields a tolerated duplicate, never a loss. With no dead-letter stream configured, a poison entry is held pending and surfaced to the operator rather than dropped.
- Poison handling by delivery count. The server-side delivery counter, not an in-process retry count, drives the poison threshold, so it survives restarts.
- Lag-guarded trimming. Retention trims by
MINIDguarded against the group low-water mark; it never evicts entries a lagging group still needs. - Partitioned ordering. An event type can declare N partition streams; order is preserved per partition, and a routing config that demands an unproven ordering axis is rejected at setup, fail-closed.
- Payload opacity. No payload bytes or credentials appear in any log, error, metric, notification, or DLQ metadata field.
Requirements
- Node.js >= 20
- Redis >= 7.0 (uses native claim-path entry removal)
- TypeScript (the package ships type declarations)
Install
npm install @logisticity/eventsPublic API
Everything is re-exported from the package root; the modules are also reachable by subpath.
src/transport-RedisStreamsTransport(implements theTransportPortcontract), the in-memory reference transport for tests, the DLQ mechanics, the partitioned binding, andRedisTransportConfig. Shared types (EventEnvelope,TransportPort,EntryId, error codes) live insrc/contracts; the injected substrates (Clock,Logger,ConnectionFactory, the operator/metrics sink) live insrc/substrate.src/envelope- the JSON envelope codec (jsonEnvelopeCodec).src/routing-createPrefixRouting/createFixedRouting, thePartitionMap(FNV-1a-64 hashing,fnv1a64), andvalidateRoutingwithRoutingRejectedError.src/validation-createZodValidation(the Zod validation adapter).src/publisher-createPublisher: a batching publisher facade overTransportPort.publishwith a bounded queue, flush-batch / linger policy, FIFO backpressure, and a no-loss shutdown.src/consumer-createConsumerRuntime: subscription orchestration and handler dispatch over the transport's frozen consume loop, plus the typed host-facingOperatorPortandMetricsPort.src/event-bus-createRedisEventBus/createEventBus: a declarative topic-map facade over the transport, publisher, and consumer runtime. Literal topic maps narrow topic and event names in TypeScript, while runtime validation rejects typos before publish or subscribe.
Documentation
- Quick start - create an event bus from a Redis URL and a topic map, then publish and subscribe with topic handles. Lower-level transport and publisher/runtime wiring is included for expert use.
- Configuration - every transport, publisher, and runtime option with its default, and the min-idle (RC-1) constraint.
- Advanced usage - partitioning and ordering, dead-lettering and poison handling, backpressure, graceful shutdown, schema validation, and recovery/cleanup tuning.
- Metrics and operator surfaces - the
OperatorPortconditions, theMetricsPortlatency rings and counters, andhealth(). - Performance - benchmark results and how to run them.
The test suites are additional runnable examples against a real Redis (start
with test/node-06.spec.ts and its RealConnectionFactory).
Development
npm run build # tsc -> dist/
npm test # jest (needs a Redis on redis://127.0.0.1:6399,
# override with REDIS_URL)
npm run bench # performance benchmark (needs Redis; see docs/performance.md)
npm run gate # deterministic gate: source-text, no-console, tsc,
# and the Proofload spec-consistency checkerThe gate is the infra-free check that must pass before any commit; the test
lanes need a live Redis and run separately. The process/ tree holds the full
build record - frozen contracts, pressure-test records, and the STATUS ledger.
License
MIT. See LICENSE.
