Skip to content

feat(data): deferred durable blob writes + combined local/remote blob refs - #187

Merged
krisnye merged 2 commits into
mainfrom
krisnye/local-remote-blobref
Aug 25, 2026
Merged

feat(data): deferred durable blob writes + combined local/remote blob refs#187
krisnye merged 2 commits into
mainfrom
krisnye/local-remote-blobref

Conversation

@krisnye

@krisnye krisnye commented Aug 25, 2026

Copy link
Copy Markdown
Collaborator

Description

Two related changes to @adobe/data's blobStore, sharing one durability model.

Part 1 — Deferred durable writes + flush()

  • New createDeferredFallbackAsyncCache(memory, storage): put awaits the fast tier and schedules the durable write in the background; match reads memory → pendingWrites → storage; flush() drains pending writes and rejects with an AggregateError on failure (no silent swallowing); repeated writes of the same key coalesce; delete waits out any in-flight write so it can't be resurrected.
  • The static blobStore uses this wrapper, so every consumer gets deferred durability by default. getRef returns after the memory write; BlobStore.flush() is the documented durability barrier.
  • serialize-to-storage now awaits blobStore.flush() before persisting refs.

Part 2 — Combined BlobRef (local + remote)

  • BlobRefSchema relaxed to a 3-member oneOf (remote-only / local-only / combined), each additionalProperties: false.
  • getBlob / hasBlob / borrowUrl are now local-first (fixes the old dispatch that sent combined refs down the remote path); remote fallback self-heals by repopulating the local cache under the known hash.
  • Opt-in verifyRemoteHash, a withRemoteUrl(ref, url) constructor, and hash-canonicalized identity so a combined ref and a local-only ref with the same hash dedup.

Test evidence

  • New unit coverage: deferred-cache mechanics (ordering, pending-after-eviction, flush drain, failure surfacing, coalescing, delete race), relaxed-schema validation, and blob-store combined-ref behaviors (local hit, remote fallback + repopulate, verify success/mismatch, withRemoteUrl validation, identity canonicalization).
  • Full monorepo: pnpm run lint, pnpm run typecheck, and pnpm test all green (3225 tests pass).

Related PRs

None.

Jira

N/A — internal library refactor; no ticket.

krisnye and others added 2 commits August 24, 2026 23:14
… refs

blobStore now defers the storage-tier write off the critical path via a new
createDeferredFallbackAsyncCache (memory -> pendingWrites -> storage read
order); getRef returns after the memory write and flush() is the durability
barrier that drains pending writes and surfaces failures. serialize-to-storage
flushes before persisting refs.

BlobRefSchema is relaxed to allow a combined { localBlobRef, remoteBlobRef }
shape; getBlob/hasBlob/borrowUrl are local-first with self-healing remote
fallback, opt-in remote-hash verification, a withRemoteUrl constructor, and
hash-canonicalized identity.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The canonicalized-key borrow test now verifies revokeObjectURL fires exactly
once, only after the last borrow across both ref shapes is returned.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@krisnye
krisnye merged commit 1ca478a into main Aug 25, 2026
3 checks passed
@krisnye
krisnye deleted the krisnye/local-remote-blobref branch August 25, 2026 16:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant