Initial Commit

This commit is contained in:
2026-05-27 23:29:53 +01:00
commit fbc70f96e6
10000 changed files with 1102152 additions and 0 deletions

View File

@@ -0,0 +1,85 @@
# `delivery-tracker`
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
`delivery-tracker` is the bounded LRU cache of
`SmsDeliveryReport` records that `SmsService` consults for
delivery status. Receipts may arrive via webhook ingest
(`tracker.ingest(report)`) or be lazily fetched from the
configured provider via `tracker.lookupOrFetch(messageId,
provider)`. The cache is bounded so a long-running service does
not retain every receipt indefinitely.
When no provider is supplied and the cache misses,
`lookupOrFetch` throws `SmsReceiptNotFoundError` (code
`SMS.RECEIPT_NOT_FOUND`) so callers can distinguish a miss from
a remote provider error.
## Features
- LRU cache keyed by `messageId`, bounded by `maxEntries`
(default 1024).
- `ingest(report)` — record / refresh a receipt; oldest entry
evicts on overflow.
- `getStatus(messageId)` — synchronous cache read; refreshes
LRU order on hit.
- `lookupOrFetch(messageId, provider?)` — cache-first, falls
back to `provider.getStatus`; result is cached on success.
- `size()` and `clear()` for observation / reset.
## Usage: Basic
```ts
import { DeliveryTracker } from "@suaveplan/sms/delivery-tracker";
const tracker = new DeliveryTracker();
tracker.ingest({
messageId: "m1",
to: "+15551234567",
status: "delivered",
timestamp: new Date(),
});
console.log(tracker.getStatus("m1"));
```
## Usage: Advanced
```ts
import { DeliveryTracker } from "@suaveplan/sms/delivery-tracker";
import { InMemorySmsProvider } from "@suaveplan/sms/in-memory-provider";
const tracker = new DeliveryTracker({ maxEntries: 4 });
const provider = new InMemorySmsProvider();
// Lazy fetch — first call hits the provider, second hits cache.
const fromProvider = await tracker.lookupOrFetch("m1", provider);
const fromCache = await tracker.lookupOrFetch("m1", provider);
```
## API Reference
- `class DeliveryTracker`
- `constructor(options?: DeliveryTrackerOptions)`
- `ingest(report: SmsDeliveryReport): void`
- `getStatus(messageId: string): SmsDeliveryReport | undefined`
- `lookupOrFetch(messageId: string, provider?: SmsProvider):
Promise<SmsDeliveryReport>`
- `size(): number`
- `clear(): void`
- `interface DeliveryTrackerOptions`
- `maxEntries?: number` (default 1024, must be ≥ 1)
## Implementation Notes
The implementation uses a plain `Map` and exploits JavaScript's
insertion-ordered iteration to maintain LRU order: on each hit
we `delete` then `set` the entry, pushing it to the back. On
`ingest`, an existing entry is deleted before re-insertion to
keep order canonical. Eviction reads the first key in the
iterator (the oldest entry) and deletes it. `lookupOrFetch`
catches no provider errors — they propagate to the caller so a
network failure on receipt fetch isn't silently swallowed.