Commit Graph

2 Commits

Author SHA1 Message Date
Suriya
cb2660a3da feat: talk to the optimizer in Doormile's own vocabulary
The client was speaking jupiter's provider dialect -- deliveryid,
pickuplat, coordinates as strings -- because that was the only endpoint
the Route Optimization API offered. rider-bike now has
/api/v1/optimization/doormile/sequence, which takes bookingid and
pickuplatitude, so the translation layer is gone.

The new endpoint validates its body; the provider one cannot, because
jupiter is live on it and tightening it would break real deliveries.
That matters here: sending the provider endpoint the wrong field names
returns HTTP 200 "Success" with every coordinate defaulted to 0.0, no
reordering and all distances zero. The Doormile endpoint rejects that
outright, and rejects 0,0 coordinates, which are inside the valid range
but are a point in the Atlantic that drags a whole route toward it.

Responses now come back properly typed, so the loose float/string
coercion is deleted rather than kept for a shape that no longer arrives.
Tests replaced to match: they run the real client against a stub server
and pin the outbound field names, the mapping back onto assignment ids,
that steps for assignments we never sent are discarded, that step 0 is
not persisted as a position, and that a failed optimise surfaces an
error instead of quietly looking like success.

Needs rider-bike deployed first; until then sequencing fails
best-effort, which leaves bookings assigned but unordered.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-11 15:29:08 +05:30
Suriya
0288fb7af8 feat: order a rider's stops using the Route Optimization API
Assignment decided who carried a booking but never what order to run
several of them in -- the one capability jupiter had that Doormile did
not. It turns out we already own the solver: routes.workolik.com is a
live in-house Route Optimization API backed by Valhalla road-network
routing, not the paid third party I had assumed. This is a client for
it, not a solver.

internal/routing posts a rider's active stops and writes back step,
previouskms, cumulativekms and ETA onto BookingAssignment. HubBatchAssign
calls it after committing a batch, which is exactly the case it exists
for: a rider used to walk away with several bookings and no order to run
them in. GetMilerAssignments now returns sequenced stops in step order,
falling back to newest-first for anything unsequenced.

Contract discovered by probing the live service -- the OpenAPI schema
types the body as a bare object array, so the field names are not
documented anywhere. They are pickuplat/pickuplong/deliverylat/
deliverylong, NOT pickuplatitude/deliverylatitude. Sending the wrong
names does not fail: it returns HTTP 200 with every coordinate defaulted
to "0.0", no reordering and all distances zero. That trap is recorded in
a comment so the next person does not lose an afternoon to it.

Numeric fields come back inconsistently typed -- previouskms as a number,
actualkms and eta as strings, some decimal -- so they are decoded loosely
and coerced, with tests pinning the coercion. Steps for deliveryids we
did not send are discarded rather than written, so an echoed or stale id
cannot reorder another rider's work.

Sequencing is best-effort throughout and runs after assignments commit.
The optimizer is a separate service over the network; it being down must
leave bookings assigned but unordered, never undo the batch. Step 0 means
"not sequenced", not "first".

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-11 15:06:24 +05:30