Running Workflows Programmatically
While workflows can be triggered through the Loopstack Studio interface, you can also start them programmatically from within your NestJS application.
Overview
Use the RunService to execute workflows in response to:
- External API requests
- Webhook events
- Scheduled cron jobs
- Internal application events
- Batch processing tasks
Basic Example
Create a Controller
import { Body, Controller, Post } from '@nestjs/common';
import { RunService } from '@loopstack/core';
import { DefaultWorkspace } from './default.workspace';
import { MyWorkflow } from './workflows/my.workflow';
@Controller()
export class AppController {
constructor(private readonly runService: RunService) {}
@Post('run-my-workflow')
async runMyWorkflow(@Body() payload: any) {
const userId = // define a user id to run the workflow
await this.runService.run(MyWorkflow.name, DefaultWorkspace.name, payload, userId);
return { message: 'Workflow run is queued.' };
}
}RunService Parameters
await this.runService.run(
workflowName: string, // The class name of your workflow
workspaceName: string, // The class name of your workspace
payload: any, // Data passed as workflow args
userId: string, // User ID for execution context
);Advanced Examples
Webhook Handler
Trigger a workflow when receiving a webhook:
import { Body, Controller, Headers, Post } from '@nestjs/common';
import { RunService } from '@loopstack/core';
@Controller('webhooks')
export class WebhookController {
constructor(private readonly runService: RunService) {}
@Post('stripe')
async handleStripeWebhook(@Body() webhookData: any, @Headers('stripe-signature') signature: string) {
await this.runService.run(
ProcessWebhookWorkflow.name,
MainWorkspace.name,
{
source: 'stripe',
event: webhookData,
receivedAt: new Date().toISOString(),
},
webhookData.userId,
);
return { received: true };
}
}Scheduled Task
Execute a workflow on a schedule using NestJS’s @Cron decorator:
import { Injectable } from '@nestjs/common';
import { Cron, CronExpression } from '@nestjs/schedule';
import { RunService } from '@loopstack/core';
@Injectable()
export class TaskScheduler {
constructor(private readonly runService: RunService) {}
@Cron(CronExpression.EVERY_DAY_AT_9AM)
async generateDailyReports() {
const users = await this.getUsersWithReportsEnabled();
for (const user of users) {
await this.runService.run(
DailyReportWorkflow.name,
ReportsWorkspace.name,
{
reportDate: new Date().toISOString(),
reportType: 'daily',
},
user.id,
);
}
}
}Batch Processing
Process multiple items by triggering workflows in parallel:
import { Injectable } from '@nestjs/common';
import { RunService } from '@loopstack/core';
@Injectable()
export class OrderProcessingService {
constructor(private readonly runService: RunService) {}
async processPendingOrders() {
const pendingOrders = await this.getPendingOrders();
const promises = pendingOrders.map((order) =>
this.runService.run(
ProcessOrderWorkflow.name,
OrdersWorkspace.name,
{
orderId: order.id,
orderData: order,
},
order.userId,
),
);
await Promise.all(promises);
return { processed: pendingOrders.length };
}
}Last updated on