Caching
Caching returns the output value of a previous run execution when it was within a defined time-range.
Use Cases
Use caching
- When reading data from a third-party system is slow or expensive.
- When the data returned changes infrequently, but is accessed frequently.
Concept
The cache feature is implemented as a Wrapper.
Importing the Wrapper bundle will provide you with a wrapper called cache.
When the cache wrapper is attached to a connector or flow, it will search for previous successful executions of that connector or flow within a configurable timeframe. If any execution is found, the output value of that execution is returned. Otherwise the child execution is started normally and its output value is returned.
As all wrappers, the cache wrapper can be statically attached and configured. Please refer to Static Wrappers for more information.
Alternatively, the cache wrapper can be dynamically attached and configured. Please refer to Dynamic Wrappers for more information.
The cache wrapper provided by Engine is considered an example which can be extended or modified to your needs.
The search for previous executions is performed using the connector or flow and the name of the execution, if given.
Scoping the match with a cache key
By default the cache reuses any recent successful execution of the same
connector or flow (optionally narrowed by execution name). That is unsafe when
the same resource is run against several distinct targets whose outputs must not
be cross-served — for example a get service-user flow run against several
installations: without a discriminator it could return installation A's
session-id to an installation-B caller.
Pass an optional cache_key to scope the match. When set, the cache only reuses
a past execution that ran with the same cache_key, and the newly started
child is tagged with it (stored as record_metadata on the execution). Matching
is exact-equality and orthogonal to the execution name (the name identifies
what ran, the cache_key identifies which target).
Reusing a per-installation session-id without ever crossing installations.
import flow_api
def handler(system: flow_api.System, this: flow_api.Execution, inputs: dict):
installation_url = inputs['installation_url']
# Only a previous "get service-user" run for THIS installation is reused,
# never another installation's, for up to 60 minutes.
session = this.using(
'cache',
max_age_minutes=60,
cache_key=installation_url,
).flow(
'get service-user',
name='get service-user',
input_value={'installation_url': installation_url},
).get('output_value')
return this.success('all done')
Parameters
Refer to the cache wrapper for its parameters.
Examples
Using a connection with caching
import flow_api
def handler(system: flow_api.System, this: flow_api.Execution, inputs: dict):
# We connect to <name-of-a-connector>.
# If there is any previous execution of the connector within the last 60 minutes,
# the output value of the previous execution is returned immediately
# without connecting to the external system.
this.using(
'cache',
max_age_minutes=60,
).connect('<name-of-a-connector>')
return this.success('all done')
Caching named connections. Although both caches use the same connector each will receive the output value of the corresponding previous execution as determined by the name of the previous execution.
import flow_api
def handler(system: flow_api.System, this: flow_api.Execution, inputs: dict):
# The cache will return the output_value of the last successful connection
# to <database> with the name "fetch data"
data = this.using(
'cache',
max_age_minutes=60,
).connect(
'database',
name='fetch data',
).get('output_value')
# The cache will return the output_value of the last successful connection to
# <database> with the name "write status"
result = this.using(
'cache',
max_age_minutes=60,
).connect(
'database',
name='write status',
).get('output_value')
return this.success('all done')