Two MultiLevelCachingStore instances pointing at the same URL must
serialize their cache-validation runs across instances so a slower
older validation cannot overwrite a newer content-hash. The queue
is keyed by datasetId (SHA-256 hash of the dataset URL, see
hashUrl).
Each entry carries an AbortController so the owning instance's
dispose() can both cancel the in-flight HTTP fetch and remove the
queue entry — preventing a closure that captured the disposed
instance from running setContentHash() against a disposed L2 store.
Cancellation is identity-scoped: a caller holds the QueueEntry
it received from ValidationQueue.serialize and passes it back to
ValidationQueue.cancel. This matters because a newer store may
have replaced the older store's entry as the map head while the older
entry (having captured the now-disposed this) is still running — the
disposing owner must abort ITS OWN entry, never "whatever is currently
the head", or it would kill the newer store's validation and let a stale
OPFS cache be served.
Invalidation event-dispatch sites (e.g. "TTL expired", "content-hash
mismatch") stay at the caller — this class only serializes, it does
NOT emit events.
Cross-instance validation serializer.
Two MultiLevelCachingStore instances pointing at the same URL must serialize their cache-validation runs across instances so a slower older validation cannot overwrite a newer content-hash. The queue is keyed by
datasetId(SHA-256 hash of the dataset URL, seehashUrl).Each entry carries an
AbortControllerso the owning instance'sdispose()can both cancel the in-flight HTTP fetch and remove the queue entry — preventing a closure that captured the disposed instance from runningsetContentHash()against a disposed L2 store.Cancellation is identity-scoped: a caller holds the QueueEntry it received from ValidationQueue.serialize and passes it back to ValidationQueue.cancel. This matters because a newer store may have replaced the older store's entry as the map head while the older entry (having captured the now-disposed
this) is still running — the disposing owner must abort ITS OWN entry, never "whatever is currently the head", or it would kill the newer store's validation and let a stale OPFS cache be served.Invalidation event-dispatch sites (e.g. "TTL expired", "content-hash mismatch") stay at the caller — this class only serializes, it does NOT emit events.