2.7 KiB
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
appendChunkIndexvia underlyingSet<number>— calling twice with the same index is a no-op. listExpired(now, ttlMs)returns every session whosecreatedAt + ttlMs <= nowso the plugin's cleanup loop has a single-call sweep API.- Strict
create(rejects duplicates) and strictupdate(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
completecan 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.
appendChunkIndexalways returns a freshUploadSessionvalue (shallow-copied with the new set) so consumers comparing references can detect updates without===foot-guns.deleteis intentionally idempotent — abort routes call it without first checking existence.