Hello!! This is not specific to SST but would be s...
# help
r
Hello!! This is not specific to SST but would be so happy if such thing already exists in SST. Consider this scenario I want to run a lambda function but at a certain time when an even comes. For example, say I want to build a tweet scheduler So I give content, time to tweet, so for example today at 2:40 pm I give my application to tweet at tomorrow 10:00 am with the content. How do we handle such cases? How do we schedule to run lambda function tomorrow at 10 am
j
We just had a discussion about this as I am implementing the same thing. Here's the thread for reference: https://serverless-stack.slack.com/archives/C01JG3B20RY/p1654835525441279 Or TLDR; 1. Use step functions 2. Run a cronjob through EventBus that checks every X time about what to run 3. Use posthook.io for a paid service 4. Use DynamoDB TTL (as long as you are ok with a potential 48 hour lag)
s
To add to @justindra, I've recently setup a step function for a similar usecase. So I'll add some example code if it helps:
Copy code
export function StateMachineFunctionsStack({ stack }: StackContext) {
	const { database } = use(DatabaseStack);
	const exampleFunction = new Function(stack, 'example-task', {
		handler: 'src/service/statemachine/example-task.main',
		environment: {
			DATABASE: DATABASE,
			CLUSTER_ARN: database.clusterArn,
			SECRET_ARN: database.secretArn,
		},
	});
	exampleFunction.attachPermissions([database]);

	return { exampleFunction };
}
Copy code
export function StateMachineStack({ stack }: StackContext) {
	const { exampleFunction } = use(StateMachineFunctionsStack);

	// Define each state
	const sWait = new sfn.Wait(stack, 'Wait', {
		time: sfn.WaitTime.duration(
			cdk.Duration.seconds(Number(process.env.TIME_DELAY) ?? 0)
		),
	});
	const sExampleTask= new tasks.LambdaInvoke(stack, 'ExampleTask', {
		lambdaFunction: exampleFunction,
		// Lambda's result is in the attribute `Payload`
		inputPath: '$',
	});

	const definition = sWait.next(sExampleTask);

	const stateMachine = new sfn.StateMachine(
		stack,
		'StateMachine',
		{
			definition,
			stateMachineName: 'StateMachine',
		}
	);

	return { stateMachine };
}
Copy code
import {
	SFNClient,
	SFNClientConfig,
	StartExecutionCommand,
	StartExecutionCommandInput,
} from '@aws-sdk/client-sfn';

export const startStateMachine = async (stateMachineARN: string, data: any) => {
	const config: SFNClientConfig = { region: 'ap-southeast-2' };
	const params: StartExecutionCommandInput = {
		stateMachineArn: stateMachineARN,
		input: JSON.stringify(data),
	};

	const client = new SFNClient(config);
	console.log('State Machine|Initiating...');
	try {
		const command = new StartExecutionCommand(params);
		await client.send(command);
		console.log('State Machine|Initiated');
	} catch (err) {
		console.log('State Machine|Failed to Initiate', err);
	}
};
r
Wow thanks a lot!!!
s
The main difference is you'd be calculating the wait duration based on the passed in event values, rather than mine which is a constant delay
r
So for every “scheduled event” we would have a “step function” ?
s
Essentially you create a step function, which is a chain of 'events', which can include lambdas, and then you have different executions of that step function
The 'wait' event, doesn't cost anything while executing, but there is a cost for a change in events, so step functions become expensive if you are executing them frequently with many events(steps)
r
Ah interesting, so if we know we are going to execute them frequently, cron would be cheaper?
I am new to
step
functions so I think I would prolly need to read more about them.
j
Yep, and Cron's accuracy would be based on how often you are running it, whereas Step Functions are pretty much run at the time you want it to run so it really depends on your use case as well