Design a generic caching system for vehicle data that minimizes the number of requests that SC must make to a given vehicle.
{
"odometer": {
"distance": 104400.50
},
"location": {
"latitude": 1234,
"longitude": 1234
}
}
- Each key in the data object has a one-to-one mapping with an endpoint on SC's
API
- Ex: odometer -> GET /odometer
- Freshness
- Validation
- Invalidation
- Server side - avoids more database operations
- Client side - avoids more network requests
- Stored in multiple types of data stores like Redis, Memcached, or just in memory
- config(obj)
- Set up a database connection string here
- Default settings like expiration time
- set(key, data, expirationTimestamp)
- Adds data to data store by key
- Set an expiration timestamp
- get(key)
- Checks if data by key exists in cache. If not, continues on with the request to get new data
- Checks if the data is expired. If it is, continues on with the request to get fresh data
- remove(key)
- Removes data by some key if it exists
- Retrieve a resource
- Resource exists in cache and is not expired, uses
get
to return cached resource. - Resource exists in cache and is expired, gets fresh data, caches through
set
and returns resource. - Resource does not exist, gets fresh data, caches through
set
and returns resource.
- Resource exists in cache and is not expired, uses
- Create or update a resource.
- Invalidates current data by using
set
to add fresh data to the cache.
- Invalidates current data by using
- Delete a resource
- Invalidates current data by using
remove
to delete the data from the cache.
- Invalidates current data by using
Concerning individual keys like odometer
and location
, there are a few different solutions.
- If the vehicle id is the key and assuming it is somehow available during requests to child resources like
/odometer
, then the whole vehicle object would be added and modified (get existing/new object>merge sub resource into parent resource>set). Invalidation issues would be obvious. - The data in vehicle data response could be broken down and stored something like
{ vehicle_id_odometer: odometerObj }
so when subsequent requests are made to the child resource, only that data is add or modified. Less invalidation issues overall since only specific parts would be added and modified as needed. Expiration times could be set shorter for properties like odometer that are updated frequently. - Only the whole vehicle data object is stored. Child resources would be plucked from the larger object and returned separately, assuming the vehicle id is available. But the whole data object has to be reset if only child resources are modified.