first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,76 @@
# errors
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
Defines the structured error surface for `@suaveplan/cache-redis`. Every failure inside the package — connection drops to the Redis server, individual command rejections, codec round-trip failures, oversized keys, invalid TTL arguments — surfaces as a `RedisCacheError` carrying one of the codes registered in `CACHE_REDIS_CODES`. Consumers programmatically branch on `error.code` rather than parsing free-form messages, and the optional `key` and `command` discriminants pinpoint exactly which command on which key triggered the failure.
## Features
- 5-code registry built with `defineCodes("CACHE_REDIS", [...])` so codes serialise identically across OpenTelemetry span events, the wire-format error envelope, and the i18n resolver.
- `RedisCacheError` extends `SuaveplanError<CacheRedisCode>` for cause chains, structured `traceId`, and arbitrary `context`.
- `key` and `command` discriminants on every error — present whenever a failure originates at a known key or command boundary.
- Every code is exercised at a real call site by `errors.test.ts`, satisfying the §13 step 0 reachability gate.
## Usage: Basic Example
```ts
import {
CACHE_REDIS_CODES,
RedisCacheError,
} from "@suaveplan/cache-redis/errors";
try {
await cache.set("k", value);
} catch (err) {
if (
err instanceof RedisCacheError &&
err.code === CACHE_REDIS_CODES.CONNECTION_FAILED
) {
metrics.increment("cache.redis.connection_failure");
}
}
```
## Usage: Advanced Example
```ts
import {
CACHE_REDIS_CODES,
RedisCacheError,
} from "@suaveplan/cache-redis/errors";
function classify(err: unknown): "retry" | "fatal" | "ignore" {
if (!(err instanceof RedisCacheError)) return "fatal";
switch (err.code) {
case CACHE_REDIS_CODES.CONNECTION_FAILED:
case CACHE_REDIS_CODES.COMMAND_FAILED:
return "retry";
case CACHE_REDIS_CODES.CODEC_ERROR:
return "ignore"; // cache miss is safe
case CACHE_REDIS_CODES.KEY_TOO_LONG:
case CACHE_REDIS_CODES.INVALID_TTL:
return "fatal";
default:
return "fatal";
}
}
```
## API Reference
| Export | Kind | Purpose |
| --- | --- | --- |
| `CACHE_REDIS_CODES` | const | Frozen object mapping reason → `"CACHE_REDIS.<REASON>"` value. |
| `CacheRedisCode` | type | Union of the registered code values. |
| `RedisCacheError` | class | Extends `SuaveplanError<CacheRedisCode>`. Constructor: `(code, messageKey, options?)` where options may carry `key`, `command`, `cause`, `context`, `traceId`. |
| `RedisCacheErrorOptions` | type | `SuaveplanErrorOptions & { key?: string; command?: string }`. |
Registered codes: `CONNECTION_FAILED`, `COMMAND_FAILED`, `CODEC_ERROR`, `KEY_TOO_LONG`, `INVALID_TTL`.
## Implementation Notes
`CONNECTION_FAILED` is intentionally the catch-all for "the underlying `RedisLike` client threw something" — the cache cannot distinguish network errors from server-side `READONLY` rejects without parsing the cause, and most consumers treat both as "retry later." `COMMAND_FAILED` is reserved for failures that originate inside the cache itself — currently only `clear()` without a namespace; future commands that have explicit semantic preconditions will share this code.