When building workflows you may need to perform operations that have side effects, like:
Sending an email
Logging
Making a database call
API requests
Having workflow as code means you are free to place these side effects anywhere in your workflow definition.But, there arises a problem since the workflow definition may be executed multiple times.
Side-effects could be executed multiple times.
The result of the side-effect may not be consistent across executions.
Copy
workflow.version(1).define(async (ctx, input) => { // ... your workflow code // ⚠️ This may run multiple times! const user = await fetch( "http://user-service.local.svc.cluster.local/users/1", ); // Rest of the workflow...});
To solve this problem, Inferable provides a memo convenience function that can be used to cache interim results.
Copy
workflow.version(1).define(async (ctx, input) => { // ... existing workflow code // ✅ This will cache the result of the fetch and return the cached result for subsequent executions const user = await ctx.memo("getUser", async () => { return fetch("http://user-service.local.svc.cluster.local/users/1"); }); // ... existing workflow code});
Whatever is returned from the memoized function is cached and can be used by subsequent steps in the workflow, or multiple executions of the same workflow, provided the executionId is the same.They are also visible in the workflow timeline.Semantics
Memoized results are cached, and scoped to an executionId.
The memoized function will return a result.
Any errors thrown inside the memoized function are returned directly to the workflow.
If your intent is to fail the workflow as a result of a side-effect, you can let the error bubble up.
If your intent is to continue the workflow despite the error, you must catch the error and continue.