Files
skills/docs/api-stack/api/api-plugin-webhook/src/dead-letter/memory.md
2026-05-29 08:20:56 +01:00

2.6 KiB

memory.ts — default in-memory DeadLetterSink

Purpose

Provides the default DeadLetterSink implementation shipped with the plugin: an unbounded Array<DeadLetterEntry> backed sink suitable for tests and development environments. The list is most-recent-first via unshift, so a caller invoking list({ limit: 10 }) always sees the ten most-recent exhausted deliveries. Production deployments typically configure a sibling sink (S3, Postgres, Mailpit) so dead letters survive process restart; this implementation exists so the plugin can boot with zero configuration and so tests can assert exhaustion behavior without standing up storage.

Features

  • record is a single unshift — O(1) on every write.
  • list walks the array applying the optional endpointId filter and limit cap; returns a frozen-by-array slice.
  • No bounded capacity — operators relying on the in-memory sink in long-running services should rotate the plugin or wire a durable sibling.

Usage: Basic

import { MemoryDeadLetterSink } from "@suaveplan/api-plugin-webhook/dead-letter/memory";

const sink = new MemoryDeadLetterSink();
const failed = await sink.list();

Usage: Advanced

import { MemoryDeadLetterSink } from "@suaveplan/api-plugin-webhook/dead-letter/memory";

const sink = new MemoryDeadLetterSink();
await sink.record({
    id: "dl-1",
    endpointId: "ep-1",
    tenantId: null,
    event: "order.created",
    payload: { id: "w-1", event: "order.created", data: {}, timestamp: "..." },
    attempts: [],
    firstAttemptAt: "2026-05-18T00:00:00.000Z",
    finalAttemptAt: "2026-05-18T00:00:00.000Z",
    reason: "5x HTTP 500",
});

const onlyForEp1 = await sink.list({ endpointId: "ep-1", limit: 5 });
console.log(onlyForEp1.length); // 1

API Reference

  • new MemoryDeadLetterSink() — no constructor arguments.
  • record(entry) — pushes the entry to the front of the internal array.
  • list(filter?) — applies the optional endpointId and limit filter and returns a snapshot. Most-recent first.

Implementation Notes

Because the sink is an unbounded array in process memory, it must NOT be used as the durable record in production systems. The plugin docs flag this — operators wire a durable sibling sink or a composite sink that records to both memory (for fast inspection) and durable storage. The implementation chose unshift over push so consumers do not need to compute reverse() for the "most-recent first" view that operators want; the small cost (O(n) per insert) is acceptable for the in-memory implementation's intended use case.