Objective
- Provide a shared routing/distance layer for dispatch optimization (slot scoring, swap suggestions, day/range optimize) that minimizes Mapbox API spend while supporting 30–65 inspector scale.
- Make distance data cacheable, batchable, and incremental so new optimization features do not multiply Matrix/Directions calls per user action.
- Enable engineering visibility into Mapbox usage per optimize run / company / day.
Background
- Product direction includes swap suggestions, full-day/range optimization, and separate inspection vs event optimize — all depend on drive-time between stops.
batchSlotOptimizingAlgo.tsalready uses Mapbox Matrix with Redis pair caching (2-day TTL), batch size 24, and Directions fallback for single pairs;GET schedule/optimal-slotsuses a 5-minute route cache.- The legacy
slotOptimizingAlgo.tspath still calls Directions per slot; dispatch map tooling usesgetDirectionsFromMapbox.tsandmilesCalculations.tsseparately — no unified budget or reuse across features. - Naive full-day optimization could generate unsustainable Matrix element counts without a deliberate strategy.
Product / engineering principles
- User-initiated optimize only — no background full-day recompute on every calendar filter change.
- Reuse cached legs — extend existing Redis keys (
mapbox:distance:{from}:{to}inbatchSlotOptimizingAlgo.ts); warm cache once per inspector-day stop list. - Budget Matrix elements — chunk by inspector route; avoid global N×N matrices; respect Mapbox 25-coordinate limits.
- Cheap pre-filter — haversine/straight-line pruning before Mapbox for candidate pairs.
- Incremental recompute — after a swap, re-score only affected legs.
- Separate live booking vs planning — narrow candidate sets for live phone booking; explicit Optimize for day/range runs.
- Observability — log Mapbox call count / matrix elements per operation.
Scope
Backend
- Consolidate or wrap distance fetching used by
batchSlotOptimizingAlgo.ts,slotOptimizingAlgo.ts,getDirectionsFromMapbox.ts, and future optimize endpoints behind one module. - Document and enforce when to skip Mapbox (non-field services already skip in batch path).
- Metrics/logging hooks for API call counts.
Frontend
- No user-facing UI required for v1 beyond existing dispatch/map consumers; optimize UIs must call backend endpoints that use the shared layer.
Acceptance criteria
- [ ] Single shared distance API used by slot scoring and optimize paths.
- [ ] Redis cache hit rate measurable; uncached pairs batched per Matrix limits.
- [ ] Documented Mapbox call budget per “optimize day” fixture (e.g. 30 inspectors, 8 stops each).
- [ ] No automatic Mapbox storms on calendar interaction without explicit user action.
References
attik-backend/src/util/functions/schedule/batchSlotOptimizingAlgo.tsattik-backend/src/util/functions/schedule/slotOptimizingAlgo.tsattik-backend/src/routes/schedule.tsattik-backend/src/util/functions/maps/getDirectionsFromMapbox.tsattik-backend/src/routes/milesCalculations.ts