Files
suaveplan/packages/networking/drive/drive-plugin-cache/src/middleware/middleware.md
2026-05-27 23:47:53 +01:00

2.9 KiB

middleware

(no submodules)

Purpose

middleware.ts builds the DriveMiddleware registered on a Drive by driveCachePlugin. The middleware intercepts read(ctx, next) to short-circuit hot paths from the cache and to populate fresh entries on a miss. write and delete interceptions are delegated to middleware.invalidation. stat and list are pure passthroughs in this iteration.

A cache is a perf optimisation, not a correctness boundary. Every underlying cache failure (get rejection, set rejection, delete rejection) is captured into stats.errors and the OTel errors_total{namespace, op} counter — and is never propagated to the consumer.

Features

  • Pre-aborted AbortSignal short-circuits the cache work and defers to next() so the inner storage surfaces canonical DRIVE.ABORTED.
  • Live AbortSignal is forwarded to cache.get for caches whose get accepts a signal.
  • shouldCache(path, bytes) predicate gates population — defaults to a 16-MiB byte ceiling matching drive-mesh-protocol's MAX_FRAME_BYTES.
  • Population enforces the byte ceiling defensively; an oversize entry raises a structured DRIVE_CACHE.CACHE_TOO_LARGE internally and is suppressed (counted on stats.errors).
  • stat and list pass straight to next() without touching the cache.

Usage: Basic

import { buildMiddleware } from "@suaveplan/drive-plugin-cache/middleware";
import { createMutableStats } from "@suaveplan/drive-plugin-cache/handle";

const stats = createMutableStats();
const mw = buildMiddleware({ cache, stats, namespace: "drive" });
drive.useMiddleware(mw);

Usage: Advanced

const mw = buildMiddleware({
  cache,
  stats,
  namespace: "media",
  invalidateOnWrite: true,
  invalidateOnDelete: false,
  shouldCache: (path, bytes) =>
    path.endsWith(".mov") && bytes.byteLength <= 8 * 1024 * 1024,
  maxEntryBytes: 8 * 1024 * 1024,
  logger,
});

API Reference

Export Shape Description
BuildMiddlewareArgs { cache; stats; namespace?; invalidateOnWrite?; invalidateOnDelete?; shouldCache?; maxEntryBytes?; logger? } Constructor bag.
buildMiddleware(args) (BuildMiddlewareArgs) => DriveMiddleware Returns the full DriveMiddleware (read + write + delete + stat + list).

Implementation Notes

The cache key is computed as ${namespace}::${ctx.path}. The :: separator avoids accidental collision with paths that already contain /. Population happens after next() resolves — i.e. only when the inner storage actually produced bytes — so a thrown next() cannot poison the cache. Symmetrically, invalidation happens after a successful write/delete next(). The optimistic alternative (delete before next()) opens a race window where a concurrent read could repopulate stale bytes between the cache delete and the storage write.