Cross-Flow Trigger
Cross-Flow trigger overview
Sometimes, you may want to have one flow invoke an execution of another flow. Common examples include:
- Parallel processing of 10s or 1000s of records
- Simplifying large and complex integrations into smaller chunks
- Creating reusable logic that can be referenced by other flows
For situations like these, we recommend using the Cross-Flow component's trigger and Invoke Flow action. Cross-flow executions are linked in Prismatic's API, and you can readily identify which flows called other flows.
Adding a cross-flow trigger
To declare that a certain flow should be invoked by others, begin the flow with a Cross-Flow Trigger.
Note that cross-flow triggers can be invoked like regular webhook triggers through their webhook URL, but invoking the sibling flow through the Invoke Flow step ensures that the flows' executions are linked.
Synchronous and asynchronous cross-flow invocations
When you configure a cross-flow trigger, you can select a Response Type of Synchronous or Asynchronous.
- If you select synchronous, your sibling flow must complete its execution within 30 seconds. The flow calling its sibling will wait for a response before continuing its execution.
- If you select asynchronous, your sibling flow can run for up to 15 minutes like usual. The flow calling its sibling will continue its execution without waiting for the sibling to finish.
Full documentation on synchronous and asynchronous invocations are available here.
Invoking a sibling flow
To invoke a sibling flow, add an Invoke Flow step to your integration. Select a sibling flow using the Flow Name input.
If you would like to send data to the sibling flow, generate the data in one step - Code or Create Object actions are great for generating payloads - and then reference that data as the Data input.
The data that you send will be available to the sibling flow via the trigger's payload under results.body.data
.
Precautions in the Cross-Flow component are in place to prevent a flow from calling itself (as it is easy to create an unintended infinite loop or fork bomb).
If you need a flow to call itself, please use caution.
You can instruct a flow to call itself by adding an HTTP step to your integration that references your flow's trigger's results.webhookUrls.Flow Name
.
Dynamically selecting a flow to invoke
Each Invoke Flow step must select a single flow to invoke. If you'd like to invoke other flows dynamically (i.e. conditionally sometimes invoke "Flow 1" and other times invoke "Flow 2"), add a Branch step and use branching logic to determine which Invoke Flow step to run.
Tracing executions across flows
When the the Cross-Flow component is used, executions that call one another are linked together within the Prismatic API.
You can access an execution's lineage
, which tells you two things:
- Which execution invoked this execution?
- Did this execution invoke any others?
Within the integration designer, you can click View linked executions beside an execution to see its lineage. In this example, our parent execution invoked three children. One of the children invoked its own child execution.
You can see linked executions within an instance's Executions tab as well, which can help when debugging an integration that calls sibling flows.
Using cross-flow triggers in code-native
If you're building a code-native integration, you can use the context.invokeFlow
function that the cross-flow component wraps in your own code.
In this example, "Parent Flow" pulls down 100 records from the JSON Placeholder API.
It breaks those records into 5 chunks of 20, and sends those chunks to "Capitalize Titles" using context.invokeFlow
.
"Capitalize Titles" is configured to be synchronous, so "Parent Flow" waits for each invocation of its sibling to complete before continuing. It accumulates the results returned from the sibling flow.
import axios from "axios";
import { flow } from "@prismatic-io/spectral";
interface Post {
userId: number;
id: number;
title: string;
body: string;
}
const CHUNK_SIZE = 20;
export const parentFlow = flow({
name: "Parent Flow",
stableKey: "parent-flow",
description: "Parent flow that invokes its sibling flow",
onExecution: async (context) => {
// Fetch 100 posts from JSON Placeholder API
const { data: posts } = await axios.get<Post[]>(
"https://jsonplaceholder.typicode.com/posts",
);
const processedTitles = [];
// Send posts to sibling flow to be capitalized, 20 at a time
for (let i = 0; i < posts.length; i += CHUNK_SIZE) {
// Get chunk of 20 posts
const chunk = posts.slice(i, i + CHUNK_SIZE);
// Invoke sibling flow with chunk of posts
const siblingFlowResponse = await context.invokeFlow(
"Capitalize Titles",
{ posts: chunk },
);
// Response was synchronous; append returned capitalized titles
// to accumulator
processedTitles.push(...siblingFlowResponse.data);
}
return { data: processedTitles };
},
});
// This flow is contrived, but simulates "work" to be done by a sibling flow
export const capitalizeTitles = flow({
name: "Capitalize Titles",
stableKey: "capitalize-titles",
description: "Capitalize titles of all posts it receives",
isSynchronous: true,
onExecution: async (context, params) => {
const { posts } = params.onTrigger.results.body.data as { posts: Post[] };
const titlesCapitalized = posts.map((post) => post.title.toUpperCase());
// Synchronously return titles of posts, capitalized.
return Promise.resolve({ data: titlesCapitalized });
},
});
export default [parentFlow, capitalizeTitles];