Luxar Viewer API Documentation - v2026.9.22
    Preparing search index...

    Multi-level caching store that implements zarrita's AsyncReadable interface. Orchestrates three tiers — L0 (decompressed in-memory chunk cache, owned by the zarrita layer), L1 (memory, in-process), L2 (OPFS, cross-tab) — over a ChunkSource that supplies the bytes.

    Implements

    • AsyncReadable
    Index
    l2Store: OPFSStore | null = null
    prefetcher: ChunkPrefetcher | null = null
    source: ChunkSource
    l2MaxSize: number
    enabled: boolean
    noOpfs: boolean = false
    debug: boolean
    shouldClearOnInit: boolean
    clearOnInitCount: number = 0
    DEFAULT_L1_SIZE: number = ...
    DEFAULT_L2_SIZE: number = ...
    validationEntry: QueueEntry | null = null
    disposed: boolean = false
    dataAbort: AbortController = ...
    l2WriteQueue: OpfsWriteQueue
    l2Epoch: number = 0
    pendingGets: Map<string, PendingGet> = ...
    invalidationCallbacks: (() => void)[] = []
    networkBytesTransferred: number = 0
    networkRequestCount: number = 0
    totalBytesServed: number = 0
    totalRequestsServed: number = 0
    l1HitCount: number = 0
    l2HitCount: number = 0
    demandNetworkRequestCount: number = 0
    BANDWIDTH_WINDOW_MS: 10000 = 10_000
    bandwidth: BandwidthWindow = ...
    • Register a callback to be invoked when caches are invalidated (e.g., clearAll, validateCache). Used by L0 DecompressedChunkCache to clear itself when L1/L2 are invalidated.

      Parameters

      • callback: () => void

      Returns void

    • Initialize the two-level cache and validate against remote dataset.

      Performs complete cache setup including OPFS initialization and content hash validation. This MUST be called before any get() operations.

      Initialization steps:

      1. Generate dataset ID from URL hash (for OPFS directory isolation)
      2. Initialize L2 OPFS store (creates directory structure)
      3. Clear cache if ?clearCache URL parameter present
      4. Validate cache by comparing content_hash with remote .zattrs

      Cache validation is CRITICAL: fetches .zattrs directly from HTTP (bypassing cache) to detect dataset changes. If content_hash differs, clears L2 completely and re-initializes. This prevents stale data.

      Returns Promise<void>

      Promise that resolves when cache is fully initialized and validated. If caching is disabled (?noCache), resolves immediately without setup.

      If OPFS is not supported (Safari < 15.2, Firefox < 111)

      If HTTP fetch of .zattrs fails (network error, 404)

      If OPFS storage quota exceeded

      const store = new MultiLevelCachingStore(url, {
      l1MaxSize: 100 * 1024 * 1024, // 100MB
      l2MaxSize: 2 * 1024 * 1024 * 1024 // 2GB
      });

      await store.init();
      console.log('Cache ready');
      // Now safe to call get()
      // Handle initialization errors gracefully
      try {
      await store.init();
      } catch (error) {
      console.error('Cache init failed:', error);
      // Fall back to direct HTTP (no caching) by reloading with ?noCache
      // (caching is controlled via URL parameters, not constructor options)
      }

      Performance: First init: ~100ms (OPFS setup + validation), Subsequent: ~10ms (validation only)

    • Get a Zarr chunk with three-level cascade: L1 memory → L2 OPFS → L3 HTTP.

      Implements zarrita's AsyncReadable interface for seamless Zarr integration. This is the primary data access method called by zarrita for ALL chunk reads.

      Cache cascade behavior:

      1. L1 Memory Cache (~1μs): Check in-memory LRU cache first
      2. L2 OPFS Cache (~1ms): Check persistent Origin Private File System if L1 miss
      3. L3 HTTP Fetch (~100ms): Fetch from remote server if both caches miss

      On successful fetch:

      • Populates L1 cache immediately
      • Populates L2 cache asynchronously (fire-and-forget)
      • Triggers prefetcher to load adjacent chunks
      • Tracks network I/O statistics

      Performance characteristics:

      • L1 hit: ~1μs (hash table lookup)
      • L2 hit: ~1ms (OPFS file read) + promotes to L1
      • L3 fetch: ~100ms (network) + populates L1 and L2

      Parameters

      • key: string

        Zarr chunk key relative to store root. Examples: - Array chunk: 'positions/0.1.2' - Metadata: '.zarray', '.zmetadata', '.zattrs' - Nested: 'group1/subgroup/array/0.0'

      • Optionaloptions: { signal?: AbortSignal }

        Zarrita read options. A supplied abort signal cancels the underlying source read for this caller.

      Returns Promise<Uint8Array<ArrayBufferLike> | undefined>

      Promise resolving to chunk data as Uint8Array, or undefined when the key does not exist (404) or the store is being disposed with its owning scene.

      AbortError when a live demand read is cancelled by its caller or cache invalidation. Rejecting is required because zarrita treats undefined as a missing chunk and substitutes fill values.

      When a source/network failure exhausts retries or the container is unreadable, so the loader can record the failure.

      // Get a chunk (called by zarrita internally)
      const chunk = await store.get('positions/0.1.2');
      if (chunk) {
      console.log(`Loaded ${chunk.byteLength} bytes`);
      // Process chunk data...
      } else {
      console.log('Chunk not found');
      }
      // Load metadata (also goes through cache)
      const zattrs = await store.get('.zattrs');
      if (zattrs) {
      const attrs = JSON.parse(new TextDecoder().decode(zattrs));
      console.log('Dataset metadata:', attrs);
      }
      // Cache cascade demonstration
      // First access: L3 fetch (~100ms)
      console.time('first');
      await store.get('positions/0.0.0');
      console.timeEnd('first'); // ~100ms

      // Second access: L1 hit (~1μs)
      console.time('second');
      await store.get('positions/0.0.0');
      console.timeEnd('second'); // ~0.001ms

      Performance: Typical access pattern: - First load: 90% L3 fetches (cold cache) - Subsequent loads: 95% L1 hits, 4% L2 hits, 1% L3 fetches - Memory usage: L1 ~100MB, L2 ~2GB (configurable)

      • init for cache initialization and validation
      • setPrefetcher for enabling automatic adjacent chunk loading
    • Get a chunk and report the failure mode structurally.

      Same L1 → L2 → L3 cascade as get, but distinguishes:

      • ok(data) — present in some tier or fetched successfully.
      • err({ kind: 'Missing' }) — server returned 404. Caller may treat as "not yet stored" without alarm.
      • err({ kind: 'NetworkError', cause }) — a non-missing HTTP failure or transient network/DNS error after retries exhausted. Caller may back off.
      • err({ kind: 'Aborted' }) — caller signal, cache invalidation, or store disposal aborted the read.
      • err({ kind: 'Fatal', cause }) — the whole container is unreadable, not just this key. MultiLevelCachingStore.get rethrows cause rather than reporting a miss, so the failure reaches the user instead of rendering an empty scene.

      Parameters

      • key: string
      • Optionaloptions: { signal?: AbortSignal; suppressPrefetch?: boolean }

      Returns Promise<Result<Uint8Array<ArrayBufferLike>, CacheError>>

    • Run the L2 → network cascade for a single key. Called at most once per key per concurrent-getter wave by getResult's pendingGets coalescer. Increments aggregate network counters once; per-caller demand counters are incremented in getResult after this resolves.

      Parameters

      • key: string
      • OptionalsharedSignal: AbortSignal

      Returns Promise<PendingGetOutcome>

    • Validate cache using content hash. Clears cache if content changed.

      Validation is serialized per dataset via a static queue keyed on datasetId, which is SHA-256(source.identity) (see hashUrl). All MultiLevelCachingStore instances pointing at the same URL share the same id and therefore the same queue, so rapid same-URL switches cannot let an older validation finish after a newer one and restore stale metadata. Each entry registers an AbortController so a subsequent dispose() on this instance can cancel both the in-flight HTTP fetch and any waiting follow-up validation that captured this.

      Parameters

      • datasetId: string

      Returns Promise<void>

    • CRIT-5: cancel every in-flight coalesced get and forget them, so a fetch that started before an invalidation cannot resurrect stale bytes by writing back into the just-cleared L1/L2 after it resolves. Each pending entry's controller signal is composed into fetchKeyChain, so abort() trips the post-arrayBuffer populate guard. Shared by the content-hash-mismatch and TTL-expiry clear paths so the two stay in lockstep.

      Returns void

    • Drop every cache tier for an invalidation (content-hash mismatch, TTL expiry, or a user-triggered clearAll). Ordering is load-bearing: abortPendingGets() runs FIRST so no in-flight coalesced fetch can pass fetchKeyChain's populate guard and repopulate a tier DURING the async clearL2() wipe — the residual window a clear-then-abort order leaves open. L2's epoch is bumped inside clearL2(); L0 is dropped via the invalidation callbacks. Shared by all three invalidation paths so they stay in lockstep.

      Returns Promise<void>

    • Clear L2 OPFS cache only.

      Bumps l2Epoch and drops queued background writes FIRST (synchronously), so a write enqueued before this clear can never land after it and resurrect stale bytes: not-yet-started tasks are dropped here, and an already-running task self-drops on its epoch re-check (with the OPFS generation counter as a final backstop). This is the single chokepoint for every L2-clearing path (clearAll, content-hash mismatch, TTL expiry, ?clearCache).

      Returns Promise<void>

    • Clear all caches (L1 + L2). Reachable mid-session from the monitor / settings "clear caches" controls and __luxarDebug, so it aborts in-flight gets FIRST (see invalidateAllTiers) to prevent stale repopulation.

      Returns Promise<void>

    • Dispose the cache store. Flushes pending writes, aborts this instance's own in-flight cache-validation entry (identity-scoped — it does NOT remove the entry from the static queue; the entry leaves the map only when its validation settles and it is still the head, so a newer same-URL store's head is left intact), and clears L1.

      The validation cancellation matters because two stores against the same URL share the static queue; without it, a closure that captured this could run setContentHash() against a disposed l2Store.

      Returns Promise<void>

    • Conditional logging based on debug mode. Errors always emit; info/warn only when debug is on. All output is routed through the shared log utility so it shows up consistently in the debug-console overlay.

      Parameters

      • message: string
      • level: "error" | "info" | "warn" = 'info'

      Returns void