14. Patterns: Cached Result
The cached result pattern is used to alleviate load on an underlying system by returning a result that is stored in Flowgear for a specific request. Typical reasons to use this pattern cases where:
- A large number of similar requests come in over a short period of time
- Querying the underlying service is slow
- Querying the underlying service is expensive in some way. For example, it might cause a lot of memory to be allocated or a lot of CPU to be used
Under the pattern, the Workflow looks up the parameters for the request to see if there is a recent result for those parameters. If one is found, that stored result is returned instead of querying the underlying service. If no match is found, the underlying service is invoked and the result is stored (cached) so that it can be returned the next time the same request is received.
Exercise 19: Cached Result
In this exercise, we'll revisit the weather service we used in an earlier exercise but this time, we'll use caching to return the temperature of a city when it has been previously requested.
Add
Web Request 2
, rename itService
and connectStart.RunNow → Service
.Set
Service.Url
tohttp://api.openweathermap.org/data/2.5/weather?q={city}&APPID={appid}&units=metric
.Add
Service.city
andService.appid
.Add a
Variable Bar
, rename itInputs
.Add
Inputs.city
andInputs.appid
as Output Properties. Setappid
to be aHidden Property
.Set the
Inputs.appid
Property value toc95dadb707ef003ac19b0236e63e348a
.Set
Inputs.city
to a city name, for exampleatlanta
.Connect
Inputs.city → Service.city
andInputs.appid → Service.appid
.Run the Workflow to check it's executing correctly.
Add a
Variable Bar
to the right ofService
, rename it toOutputs
.Add
Outputs.temperature
.Connect
Service.ResponseBody → Outputs.temperature
, set the Data Mapping Expression tomain.temp
.Next, we will add a Key/Value to store the temperature of a city that has been queried.
Move
Outputs
one block to the right and addSet Key-Value 2
, rename itStore Temp
, connectService → Store Temp
.Set
Store Temp.Group
totemperature
.Connect
Inputs.city → Store Temp.Key
.Connect
Service.ResponseBody → Store Temp.Value
, set the Data Mapping Expression tomain.temp
.Run the Workflow and confirm the Set Key/Value step is storing the temperature correctly.
Now we will introduce a test to determine whether the temperature for a city is already in the Key/Value store which is acting as our cache.
Move
Service
three blocks to the right, in the space created, addGet Key-Value 2
, rename toQuery Temp
, addDateTime Compare
, rename toCompare
and addIf
.Reconnect
Start.RunNow → Query Temp
,Query Temp → Compare
,Compare → If
andIf.False → Service
.Connect
Query Temp.Missing → Service
.Set
Query Temp.MatchGroup
totemperature
.Connect
Inputs.city → Query Temp.Key
.Connect
Query Temp.DateTime → Compare.DateTime1
.Set
Compare.TimeSpanUnit
toSeconds
.The
DateTime Compare
Node returns the difference between two dates and times. If one of theDateTime
Properties is left empty, it defaults to the current UTC time for the comparison.Connect
Compare.TimeSpan → If.Value
.Set
If.Expression
toValue < 60
.We are setting 60 seconds as the cache expiry period. This means that we will serve a temperature for a city from cache until that record is 60 seconds old.
Connect
Query Temp.Value → Outputs.temperature
.Run the Workflow to see it re-cache the temperature for Atlanta, then run it again and it should return the cached temperature. Wait 60 seconds to see the cache invalidate and query the weather service again.
Note that we don't need to connect any further steps to the
If
NodeTrue
Output because we already injected the temperature toOutputs.temperature
fromQuery Temp.Value
.Notice also that the Workflow runs very quickly when operating through the cache since the "expensive" step of invoking the weather service is skipped.
Save and run your Workflow, then click Submit Exercise
to grade it.