We'll use a RESTful API for our system. There's basically one endpoint that would suffice the requirements. Both current location's weather information, as well as a searched city can be retrieved from a single endpoint.
This endpoint looks as:
GET /weather/:city
The :city param is the geohash of the particular city.
The response looks as follows:
[{time: timestamp, temperature: int, humidity: int}]
So we assume that the data for the weather forecast will be retrieved from an API, WeatherAPI in this case.
As calling the API is both expensive in terms of cost and performance, we'd need to have a proper mechanism to cache the retrieved data on our side.
For this purpose let's assume that we store the data per city and define that city as a geohash to be stored as a key.
The value of each city (geohash) will be a JSON object looking like:
[{time: timestamp, temperature: int, humidity: int}]
So it will be an array of objects. It will be a 24 hr forecast for each day, meaning that we'll store 24 objects. Each timestamp is representing an hr forecast and the object consists also of temperature and humidity information.
So the redis data will be stored as
KEY - city geohash , VALUE: [{time: timestamp, temperature: int, humidity: int}]
flowchart TD
n0["Client"];
n1["Weather Service"];
n2["3rd Party Weather API"];
n3[("Redis Cache")];
n0 --> n1;
n1 --> n2;
n1 --> n3;
n1 --> n0;
The client calls the Weather Service with a particular location request.
The Weather Service checks the Cache if the geohash for the city exists in the redis cache. If so the value is returned. Otherwise it's retrieved from the 3rd party and written to the cache again. Then the result is returned to the user
Our high level design outlines the important components, but it's not enough for a scalable architecture. Here's a a proposal for the detailed design:
flowchart TD
n0["Mobile"];
n1["Weather Service"];
n4["Web"];
n5["Load Balancer"];
n7[("Redis Replica Americas")];
n8[("Redis Replica Europe")];
n9[("Redis Replica Asia")];
n10[("Redis Replica Pacifics")];
n11["Gateway"];
n12["3rd Party Weather API"];
n4 --> n5;
n0 --> n5;
n5 --> n1;
n1 --> n11;
n11 --> n7;
n11 --> n8;
n11 --> n9;
n11 --> n10;
n1 --> n12;