Skip to content

feat: integrate OSRM route service with customer live tracking#760

Open
CoderMS07 wants to merge 2 commits into
KanishJebaMathewM:mainfrom
CoderMS07:feature/customer-route-polyline
Open

feat: integrate OSRM route service with customer live tracking#760
CoderMS07 wants to merge 2 commits into
KanishJebaMathewM:mainfrom
CoderMS07:feature/customer-route-polyline

Conversation

@CoderMS07

@CoderMS07 CoderMS07 commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Summary

This PR integrates the OSRM route service with the customer live tracking experience and replaces straight-line or missing routes with dynamically generated road-following polylines.

Changes Made

Backend

backend/api/src/services/osrm.js

  • Added getRouteGeometry() for fetching route geometry from OSRM.
  • Added Redis caching for route geometries (30-second TTL).
  • Added buildStraightLineGeometry() fallback when OSRM is unavailable.
  • Added GeoJSON LineString support for map rendering.

backend/api/src/routes/orderRoutes.js

  • Added authenticated endpoint:
GET /api/orders/:displayId/route
  • Loads order information.
  • Retrieves the latest driver telemetry from MongoDB.
  • Generates road routes using OSRM.
  • Falls back to a straight-line route if OSRM is unavailable.
  • Enforces authorization so only the assigned driver or order owner can access the route.

Flutter

apps/customer/lib/services/order_service.dart

  • Added fetchOrderRoute() API integration.

apps/customer/lib/screens/live_tracking_screen.dart

  • Added route loading logic.
  • Decodes GeoJSON coordinates into map points.
  • Renders road-following polylines.
  • Refreshes routes every 30 seconds.
  • Prevents duplicate route requests.
  • Cancels timers during dispose.
  • Displays a loading indicator while fetching the initial route.

Error Handling

  • Handles OSRM failures gracefully.
  • Falls back to a straight-line route.
  • Handles missing telemetry records.
  • Prevents route requests from causing UI crashes.

Performance Improvements

  • Added 30-second refresh interval.
  • Added short-lived Redis caching for route geometries.
  • Prevented duplicate requests during rebuilds.
  • Avoided unnecessary map updates.

Verification

  • Backend starts successfully (npm run dev).
  • Flutter analyzer passes with no issues.
  • Customer app builds successfully.
  • Route refresh timer and disposal logic verified.
  • Integration tested to the extent possible without production environment variables.

Checklist

  • Implemented GET /api/orders/:displayId/route
  • Used latest driver telemetry
  • Integrated OSRM route generation
  • Added GeoJSON route responses
  • Integrated route fetching into Flutter
  • Rendered map polylines
  • Added automatic 30-second refresh
  • Prevented duplicate requests
  • Added straight-line fallback
  • Added loading state
  • Preserved smooth tracking experience

Closes #582

Summary by CodeRabbit

Release Notes

New Features

  • Live route tracking now periodically refreshes to keep the displayed route geometry current.
  • While the route is loading, the Live header shows a spinner with “Loading route...”.
  • Live routing now falls back to a direct line route when road geometry can’t be generated.

Bug Fixes

  • Improved refresh behavior to prevent overlapping/concurrent route requests and reduce unnecessary map updates, resulting in smoother live tracking.

Copilot AI review requested due to automatic review settings June 23, 2026 06:08
@github-actions

Copy link
Copy Markdown
Contributor

🎉 Thank you for your contribution! Your pull request has been received and will be reviewed shortly.

If you enjoy the project, please consider giving the repository a ⭐. You can also follow my GitHub profile to stay updated on future open-source projects.

Thanks for being part of the community! 🚀

@coderabbitai

coderabbitai Bot commented Jun 23, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: c74be66f-f0c9-46b7-91b8-9333505f7a29

📥 Commits

Reviewing files that changed from the base of the PR and between 97542d4 and 16adc9b.

📒 Files selected for processing (4)
  • apps/customer/lib/screens/live_tracking_screen.dart
  • apps/customer/lib/services/order_service.dart
  • backend/api/src/routes/orderRoutes.js
  • backend/api/src/services/osrm.js
💤 Files with no reviewable changes (2)
  • backend/api/src/services/osrm.js
  • backend/api/src/routes/orderRoutes.js
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/customer/lib/services/order_service.dart
  • apps/customer/lib/screens/live_tracking_screen.dart

📝 Walkthrough

Walkthrough

Adds live route tracking end to end: OSRM geometry helpers feed a new authenticated order route endpoint, and the customer app now polls that endpoint on a timer to render an updating route polyline with loading-state feedback.

Changes

Live Route Tracking via OSRM

Layer / File(s) Summary
OSRM geometry functions and caching
backend/api/src/services/osrm.js
Adds geometry route URL and cache-key helpers, a Redis-backed getRouteGeometry with TTL caching, buildStraightLineGeometry, a geometry TTL constant, and updated testing exports.
GET /:id/route endpoint
backend/api/src/routes/orderRoutes.js
Expands the OSRM import and adds a new authenticated route endpoint with order lookup, role-based access checks, telemetry-based origin coordinates, OSRM geometry lookup, straight-line fallback, and structured error responses.
Flutter route polling and rendering
apps/customer/lib/services/order_service.dart, apps/customer/lib/screens/live_tracking_screen.dart
Adds fetchOrderRoute and updates live tracking with periodic route refresh, request throttling, coordinate parsing, route-point updates, and a loading indicator while the route is first fetched.

Sequence Diagram(s)

sequenceDiagram
  participant LiveTrackingScreen
  participant OrderService
  participant orderRoutes
  participant telemetry
  participant getRouteGeometry

  LiveTrackingScreen->>OrderService: fetchOrderRoute(orderDisplayId)
  OrderService->>orderRoutes: GET /api/orders/:id/route
  orderRoutes->>telemetry: latest driver coordinates
  telemetry-->>orderRoutes: origin coords
  orderRoutes->>getRouteGeometry: origin and destination coordinates
  getRouteGeometry-->>orderRoutes: GeoJSON Feature or null
  orderRoutes-->>OrderService: geometry + fallback
  OrderService-->>LiveTrackingScreen: route data
  LiveTrackingScreen->>LiveTrackingScreen: parse coords and update polyline
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Suggested labels

level:advanced

Poem

🐇 I hop where the road bends light,
A winding path in morning bright.
Thirty seconds, تازه trail anew,
Telemetry and OSRM too.
My little map now knows the way,
And traces drivers day by day.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: integrating the OSRM route service into customer live tracking.
Linked Issues check ✅ Passed The changes implement the route endpoint, OSRM fallback, Flutter route loading, and 30-second refreshes described in #582.
Out of Scope Changes check ✅ Passed No clear unrelated code changes stand out beyond the requested route and live-tracking updates.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Integrates OSRM-based road-following route geometry into the customer live tracking experience by adding a backend route-geometry endpoint (with Redis caching + straight-line fallback) and wiring the Flutter client to periodically fetch and render the returned GeoJSON LineString as a polyline.

Changes:

  • Backend: add OSRM GeoJSON route fetching + short-lived Redis caching and a straight-line fallback geometry.
  • Backend: add authenticated GET /api/orders/:id/route endpoint that uses latest MongoDB telemetry as the route origin and enforces customer/driver authorization.
  • Flutter: add route fetch API + periodic refresh and render the returned geometry as a map polyline with an initial loading indicator.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
backend/api/src/services/osrm.js Adds OSRM geometry fetcher returning GeoJSON Feature(LineString), with Redis caching + straight-line fallback helper.
backend/api/src/routes/orderRoutes.js Adds authenticated/authorized /route endpoint to return live route geometry based on latest telemetry.
apps/customer/lib/services/order_service.dart Adds fetchOrderRoute() to call the new backend endpoint.
apps/customer/lib/screens/live_tracking_screen.dart Periodically fetches route geometry and renders it as a polyline; shows loading state on initial load.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +324 to +333
_isFetchingRoute = true;
final isFirstLoad = _lastRouteFetchAt == null;
if (isFirstLoad && mounted) {
setState(() => _isRouteLoading = true);
}

try {
final routeData = await _orderService.fetchOrderRoute(widget.orderId);
_lastRouteFetchAt = DateTime.now();

Comment on lines +87 to +95
function buildGeometryUrl({ originLat, originLng, destLat, destLng }) {
const baseUrl = process.env.OSRM_BASE_URL || DEFAULT_OSRM_BASE_URL;
const url = new URL('/route/v1/driving/', baseUrl);
url.pathname += `${originLng},${originLat};${destLng},${destLat}`;
url.searchParams.set('overview', 'full');
url.searchParams.set('geometries', 'geojson');
url.searchParams.set('alternatives', 'false');
url.searchParams.set('steps', 'false');
return url;
Comment on lines +1194 to +1203
router.get('/:id/route', authenticate, requireRole(['customer', 'driver']), validateParams(paramIdSchema), async (req, res) => {
const orderId = req.params.id; // this is order_display_id from client

try {
// 1. Resolve order and check authentication / authorization
const { data: order, error: orderErr } = await supabase
.from('orders')
.select('id, customer_id, driver_id, status, pickup_lat, pickup_lng, drop_lat, drop_lng')
.eq('order_display_id', orderId)
.maybeSingle();

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/customer/lib/screens/live_tracking_screen.dart`:
- Around line 353-357: The setState block in the live tracking screen updates
_routePoints on every poll without checking if the points have actually changed,
causing unnecessary map redraws. Add a condition before the setState call to
check if the new points are different from the current _routePoints value, and
only call setState if they differ. This prevents redundant updates when
coordinates remain identical between polls.

In `@backend/api/src/routes/orderRoutes.js`:
- Around line 1251-1253: After converting order.drop_lat and order.drop_lng to
numbers using Number() function, add validation checks to ensure the resulting
destLat and destLng values are valid numbers and not NaN. If either value is
NaN, return a clear 400 Bad Request error with a descriptive message about
invalid input data instead of allowing the invalid values to proceed to
OSRM/fallback functions. Apply the same validation logic to the pickup
coordinate conversions at lines 1265-1267 for pickup_lat and pickup_lng.

In `@backend/api/src/services/osrm.js`:
- Around line 98-101: In the buildGeometryCacheKey function, the rounding helper
function r currently uses toFixed(3) which limits precision to approximately 100
meters. Increase the number of decimal places passed to toFixed() to a higher
value (such as 5 or 6) to preserve finer-grained location accuracy and prevent
nearby GPS points from reusing the same cached polyline.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: d6dc597e-8d83-4b38-9dac-d15d394c7f0e

📥 Commits

Reviewing files that changed from the base of the PR and between 5ac71a8 and f09541f.

📒 Files selected for processing (4)
  • apps/customer/lib/screens/live_tracking_screen.dart
  • apps/customer/lib/services/order_service.dart
  • backend/api/src/routes/orderRoutes.js
  • backend/api/src/services/osrm.js

Comment thread apps/customer/lib/screens/live_tracking_screen.dart Outdated
Comment on lines +1251 to +1253
const destLat = Number(order.drop_lat);
const destLng = Number(order.drop_lng);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Validate destination numbers after conversion before calling OSRM/fallback.

If drop_lat/drop_lng are non-numeric strings, Number(...) yields NaN; this path currently returns a generic 502 instead of a clear data error.

💡 Proposed fix
     const destLat = Number(order.drop_lat);
     const destLng = Number(order.drop_lng);
+    if (!Number.isFinite(destLat) || !Number.isFinite(destLng)) {
+      return res.status(500).json({ error: 'Order has invalid destination coordinates.' });
+    }
 
     // 3. Call OSRM for a road-following route, falling back to a straight
     // line if OSRM is unavailable so the tracking screen never goes blank.

Also applies to: 1265-1267

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/api/src/routes/orderRoutes.js` around lines 1251 - 1253, After
converting order.drop_lat and order.drop_lng to numbers using Number() function,
add validation checks to ensure the resulting destLat and destLng values are
valid numbers and not NaN. If either value is NaN, return a clear 400 Bad
Request error with a descriptive message about invalid input data instead of
allowing the invalid values to proceed to OSRM/fallback functions. Apply the
same validation logic to the pickup coordinate conversions at lines 1265-1267
for pickup_lat and pickup_lng.

Comment thread backend/api/src/services/osrm.js
@CoderMS07

Copy link
Copy Markdown
Contributor Author

Hi @KanishJebaMathewM, Could you please add the appropriate difficulty label to this PR? Thank you!

@CoderMS07 CoderMS07 force-pushed the feature/customer-route-polyline branch from 97542d4 to 16adc9b Compare June 24, 2026 05:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

# [INTEGRATION] Wire OSRM Route Service to Customer Live Tracking Map Polyline

2 participants