Build a real-time location tracking app with GraphQL Subscriptions

In this article, you will learn how to build an application that tracks the location of a vehicle in real-time.

The application is built with:

  • Hasura GraphQL Engine for backend
  • React and Apollo for frontend

The Hasura GraphQL Engine enables you to create the real-time GraphQL API for the application without writing any backend code.

The application also makes use of Hasura’s GraphQL Engine real-time capabilities using subscriptions.

Real-time Tracking Location Application Preview

The above picture illustrates the final real-time location tracking application.

Data Modeling

It’s important to mention that the focus of the tutorial is on the data models we store in Postgres and the GraphQL operations on the frontend. Rather than the complete application functionality.

Vehicle

Since the application tracks the location of a vehicle, we need to store vehicle information in the database.

vehicle (
  id TEXT PRIMARY KEY
  name TEXT NOT NULL
)

We only store the id and the name of the vehicles.

Vehicle Location

The vehicle will have multiple locations during its journey, so we need to store those locations.

vehicle_location (
  id INT NOT NULL PRIMARY KEY nextval(vehicle_loc)
  vehicle_id TEXT FOREIGN KEY REFERENCES vehicle(id) NOT NULL
  location TEXT NOT NULL
  "timestamp" timestamp with time zone DEFAULT now() NOT NULL
)

For each location, we need the following:

  • location id
  • vehicle id
  • location - the location is a set of coordinates
  • timestamp

Vehicle Location Sequence

In the previous table - vehicle_location - we stored the id of the location. Instead of auto-incrementing the id, we create and use a sequence.

A sequence represents an ordered list of integers and it can be used as a primary key.

CREATE SEQUENCE public.vehicle_loc
    START WITH 1
    INCREMENT BY 1
    NO MINVALUE
    NO MAXVALUE
    CACHE 1;

The above sequence starts from "1" and then it gets incremented by "1" each time.

Next Step

We are done with the data modeling and we can move on to the next step - writing the GraphQL Operations.

Frontend - GraphQL Operations

There are four GraphQL operations for this application:

  1. a mutation to insert a vehicle
  2. a mutation to insert the location of a vehicle
  3. a subscription to get the vehicle
  4. a subscription to get the location of a vehicle

Insert Vehicle

When you start the application and click on the TRACK LOCATION button, a new vehicle gets inserted into the database.

mutation insert_vehicle ($objects: [vehicle_insert_input!]! )  {
  insert_vehicle (objects: $objects){
    returning {
      id
    }
  }
 }

The application tracks the newly-inserted vehicle during its journey.

Insert Vehicle Location

Once the vehicle is inserted into the database, we also need to insert the vehicle location.

mutation insert_vehicle_location ($objects: [vehicle_location_insert_input!]! )  {
  insert_vehicle_location (objects: $objects){
    returning {
      id
    }
  }
}

Considering that the vehicle has multiple locations during its journey, the mutation insert_vehicle_location runs every three seconds.

With React Hooks, you can run the mutation every three seconds with the help of useEffect and useInterval hooks. The useEffect hook comes with React by default, but the useInterval is a custom hook.

Subscribing to the Vehicle Location

We want to be notified each time the vehicle changes its location. GraphQL Subscriptions allow us to do that!

The following query only returns the latest vehicle location:

subscription getLocation($vehicleId: String!) {
  vehicle(where: {id: {_eq: $vehicleId}}) {
    locations(order_by: {timestamp:desc}, limit: 1) {
      location
      timestamp
    }
  }
}

GraphQL notifies the client about the changes whenever the vehicle location changes and the user interface gets updated.

As a result, you see the vehicle moving on the map.

Vehicle Subscription

Similarly, we can subscribe to the vehicle.

subscription getVehicle($vehicleId: String!) {
  vehicle (where: { id: { _eq: $vehicleId }}) {
    id
    name
  }
}

The subscription returns the id and the name of the vehicle.

Application Code and Demo

Head over to realtime-location-tracking.demo.hasura.app to see the application live.

The complete application code is available on GitHub.

Blog
25 Feb, 2022
Email
Subscribe to stay up-to-date on all things Hasura. One newsletter, once a month.
Loading...
v3-pattern
Accelerate development and data access with radically reduced complexity.