Files
skills/docs/api-stack/api/api-plugin-file-upload/src/session-store/memory.md
2026-05-29 08:20:56 +01:00

2.7 KiB

memory.ts

(no submodules)

Purpose

In-memory UploadSessionStore adapter. Tracks both in-flight UploadSession state (sessions Map) and completed UploadRecord metadata (records Map) so GET /uploads/{uploadId} works against either an in-progress chunked upload OR a completed single-shot upload uniformly. Used as the default store when createFileUploadPlugin is invoked without an explicit sessionStore option.

Features

  • Idempotent appendChunkIndex via underlying Set<number> — calling twice with the same index is a no-op.
  • listExpired(now, ttlMs) returns every session whose createdAt + ttlMs <= now so the plugin's cleanup loop has a single-call sweep API.
  • Strict create (rejects duplicates) and strict update (rejects missing) so logic bugs in the service layer surface immediately rather than silently writing the wrong record.
  • Records are stored separately from sessions so complete can swap session → record atomically without leaving an in-flight reference behind.

Usage: Basic

import { MemoryUploadSessionStore } from "@suaveplan/api-plugin-file-upload/session-store/memory";

const store = new MemoryUploadSessionStore();
await store.create(session);
const fetched = await store.read(session.uploadId);

Usage: Advanced

import { MemoryUploadSessionStore } from "@suaveplan/api-plugin-file-upload";

const store = new MemoryUploadSessionStore();
await store.create(session);
await store.appendChunkIndex(session.uploadId, 0);
await store.appendChunkIndex(session.uploadId, 0); // idempotent
const expired = await store.listExpired(Date.now() + 60_000, 1000);
for (const s of expired) await store.delete(s.uploadId);

API Reference

  • class MemoryUploadSessionStore implements UploadSessionStore — constructor takes no arguments.
  • create(session) / read(id) / update(session) / delete(id) — standard CRUD.
  • appendChunkIndex(id, index): Promise<UploadSession> — returns the updated session.
  • listExpired(now, ttlMs): Promise<readonly UploadSession[]> — TTL sweep.
  • readRecord(id) / saveRecord(record) / deleteRecord(id) — record-side CRUD.

Implementation Notes

  • The session and record maps are kept distinct because a single upload transitions session → record atomically; conflating them would force the caller to encode that transition with an enum field on a union type.
  • appendChunkIndex always returns a fresh UploadSession value (shallow-copied with the new set) so consumers comparing references can detect updates without === foot-guns.
  • delete is intentionally idempotent — abort routes call it without first checking existence.