Skip to content

Offline Geospatial Tile Prefetch Scheduler with LRU Eviction and Predictive Heatmap Caching #48

Description

@elizabetheonoja-art

Problem Statement / Feature Objective

Field operators frequently lose connectivity in remote utility corridors, rendering Mapbox vector tiles irretrievable from the CDN. A predictive tile prefetch scheduler must anticipate the operator's viewport trajectory based on GPS heading, velocity, and zoom delta, then download and cache tiles into IndexedDB with a bounded LRU eviction policy. The system must also pre-warm adjacent LOD pyramid levels so that pinch-zoom gestures do not trigger tile fallback to grey squares. This directly impacts offline-first reliability for field tablet deployments.

Technical Invariants & Bounds

  • Tile cache capacity: hard limit of 2,500 vector tile entries (each ~15–80 KB, mean 42 KB); eviction triggers at 2,250 entries via LRU chain.
  • Predictive window: fetch tiles within a 3×3 grid at current zoom, plus two zoom levels above and below (total 9×5 = 45 tiles burst).
  • GPS sampling: 1 Hz position updates; velocity threshold > 2 m/s triggers prefect; stale heading > 30° cancels pending requests.
  • IndexedDB object store uses tile ID (z/x/y) as key; each entry stores tile blob, fetched timestamp, access counter, and last-access timestamp.
  • Stale tile TTL: 7 days for zoom ≤14, 48 hours for zoom ≥15; eviction prefers lowest (access_count / age) ratio.

Codebase Navigation Guide

  • src/services/tileCache.ts — IndexedDB tile store open/close, put/get/delete operations.
  • src/hooks/useMapViewport.ts — Exposes viewport center, zoom, pitch, bearing from Mapbox camera.
  • src/hooks/useGeoLocation.ts — Watches navigator.geolocation with 1 Hz callback; yields coords, heading, speed.
  • src/workers/tilePrefetch.worker.ts — Web Worker that receives bounding-box + zoom range, issues fetch requests off the main thread, and writes results into the shared IndexedDB.
  • src/utils/lruEviction.ts — Doubly-linked list implementation of LRU eviction decision logic.
  • src/store/slices/tileCacheSlice.ts — Redux slice tracking cache stats (hits, misses, evictions, byte count).

Implementation Blueprint

  1. Implement class in with , , — maintain a doubly-linked list sorted by (access_count / age).
  2. Open IndexedDB in ; create object stores for tile blobs and a metadata store for summary counters.
  3. In + , derive a predicted bounding box using lookahead; dispatch a action.
  4. The worker in listens for these requests, validates against current LRU state (skip if tile already cached and fresh), issues for each tile URL, and writes blob + timestamp into IndexedDB.
  5. Wire lifecycle via hook; terminate worker when map component unmounts.
  6. Add an eviction watcher: after every batch of 10 writes, check ; if true, run where .
  7. Surface cache health metrics in a debug overlay (hit ratio, byte usage, pending downloads) gated behind a feature flag.

Metadata

Metadata

Assignees

Labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions