nibble-4bits / aws-local-stepfunctions Goto Github PK
View Code? Open in Web Editor NEWRun and test your AWS Step Functions locally! ๐
Home Page: https://npmjs.com/package/aws-local-stepfunctions
License: MIT License
Run and test your AWS Step Functions locally! ๐
Home Page: https://npmjs.com/package/aws-local-stepfunctions
License: MIT License
For some reason the Fail state is not recognised.
import { StateMachine, ExecutionError } from 'aws-local-stepfunctions';
const machineDefinition = JSON.parse(JSON.stringify({
StartAt: 'ErrorState',
States: {
ErrorState: {
Type: 'Fail',
Error: '500',
Cause: 'Some nasty error',
End: true
}
},
}));
test('should throw an error if name is missing', async () => {
// GIVEN
const myInput = {};
// WHEN
const stateMachine = new StateMachine(machineDefinition, {
// validationOptions: {
// noValidate: true,
// },
});
try {
const execution = stateMachine.run(myInput);
await execution.result;
} catch (e: any) {
expect(e.message).toMatch('Execution has failed with the following error: Some nasty error');
}
});
The state machine should thrown an ExecutionError
State machine definition is invalid, see error(s) below:
SCHEMA_VALIDATION_FAILED: /States/ErrorState is invalid. must match exactly one schema in oneOf
If I disable the state machine validation, the exception is thrown correctly.
Step functions allows us to refer to the input using the context Object. Although the library allows me to specify the context, would be nice if the input would be added automatically to the context:
import { StateMachine } from 'aws-local-stepfunctions';
const machineDefinition = JSON.parse(JSON.stringify({
StartAt: 'FilterInput',
States: {
FilterInput: {
Type: 'Pass',
Parameters: {
'foo.$': '$$.Execution.Input.MyObject.foo'
},
End: true
}
},
}));
test('OK', async () => {
// GIVEN
const myInput = {
MyObject: {
foo: 'bar'
}
};
// WHEN
const stateMachine = new StateMachine(machineDefinition);
const execution = stateMachine.run(myInput, {
// context: {
// Execution: {
// Input: myInput
// }
// }
});
const result = await execution.result;
console.log(result);
// THEN
expect(result).toStrictEqual({ foo: 'bar' });
});
$$.Execution.Input
should point to the stateMachine run input.
Cause:
States.Runtime: Path expression '$$.Execution.Input.MyObject.foo' does not point to a value
To make it work, I can manually build the context
object and pass to the stateMachine run method.
The AWS Step Functions API exposes an StopExecution
method which can be used to stop a running execution of a step function: https://docs.aws.amazon.com/step-functions/latest/apireference/API_StopExecution.html
Similarly, it would be useful to have the ability to abort the execution of a state machine when necessary.
Calling the package as a CLI can be a useful feature for consumers not wanting/needing to go through the hassle of creating a Node script to run a state machine
I'm thinking of something like this:
aws-local-stepfunctions --definition "{ [state machine definition goes here] }" --input '{ "num1": 5, "num2": 4 }'
And the result of the execution would be printed to stdout
Currently, the generated build can only be run in a Node environment. So some adjustments are necessary to produce a build that can be run in the browser
It would be a nice feature/option to have, being able to run the Lambda locally, if the code is provided or exists locally, as in Serverless projects, for example.
Advantages:
Task
states, as the Lambda is run locally instead of invoking it in AWSAdd support for Intrinsic Functions, as specified in the Amazon States Language spec: https://states-language.net/spec.html#appendix-b
When I try to return an array from a pass state parameters, the convert it to an object.
import { StateMachine } from 'aws-local-stepfunctions';
const machineDefinition = JSON.parse(JSON.stringify({
StartAt: 'FilterInput',
States: {
FilterInput: {
Type: 'Pass',
Parameters: [{
foo: 'bar'
}],
// Result: [{
// foo: 'bar'
// }],
End: true
}
},
}));
test('OK', async () => {
// GIVEN
const myInput = {};
// WHEN
const stateMachine = new StateMachine(machineDefinition);
const execution = stateMachine.run(myInput);
const result = await execution.result;
// THEN
expect(result).toStrictEqual([{foo: 'bar'}]);
});
The state machine should return the array
expect(received).toStrictEqual(expected) // deep equality
Expected: [{"foo": "bar"}]
Received: {"0": {"foo": "bar"}}
If I set the empty array in the Result
, it works, but it's not a viable solution.
Currently, when passing input to the CLI from stdin, the CLI assumes each line of stdin is a single JSON value.
For instance, if we have the following file input file:
input.json
{
"num1": 5,
"num2": 3
}
And call:
local-sfn -f state-machine.asl.json < input.json
local-sfn
will exit with an error because it tried to parse the first line ({
) as a JSON value.
A more robust implementation would see that this input is a single JSON value, even if it is defined across multiple lines.
The StepFunctions implementation of JsonPath allow us to filter elements using the ?()
syntax.
When I try to test a state machine that use a filter, the validation fails and if I try to bypass the validation, the engine returns an error.
import { StateMachine } from 'aws-local-stepfunctions';
const machineDefinition = JSON.parse(JSON.stringify({
StartAt: 'GetSubjects',
States: {
GetSubjects: {
Type: 'Task',
Resource: 'arn:aws:lambda:us-east-1:123456789012:function:GetSubjects',
Next: 'ReturnResult'
},
ReturnResult: {
Type: 'Pass',
Parameters: {
'completed_los.$': '$.Payload[?(@.subject_status==subject_completed)]..subject_id',
},
End: true
}
},
}));
test('OK', async () => {
// GIVEN
const myInput = {};
// WHEN
const stateMachine = new StateMachine(machineDefinition, {
// validationOptions: {
// checkPaths: false,
// }
});
const execution = stateMachine.run(myInput, {
overrides: {
taskResourceLocalHandlers: {
"GetSubjects": ((event: any) => {
return {
Payload: [
{ subject_id: 1, subject_status: 'subject_completed' },
{ subject_id: 2, subject_status: 'subject_completed' },
{ subject_id: 3, subject_status: 'subject_added' }
]
}
})
},
},
});
const result = await execution.result;
console.log(result);
// THEN
expect(result).toStrictEqual([1,2]);
});
The state machine should process the JsonPath filter.
tate machine definition is invalid, see error(s) below:
SCHEMA_VALIDATION_FAILED: /States/ReturnResult/Parameters/completed_los.$ is invalid. must match format "asl_payload_template"
By setting checkPaths: false
, the state machine is executed, but I get the following error:
ExecutionError: Execution has failed with the following error: jsonPath: subject_completed is not defined: @.subject_status==subject_completed
By changing the definition to wrap the condition with double quotes $.Payload[?(@.subject_status=="subject_completed")]..subject_id
, it works, but unfortunately that doesn't work on step function:
To make it work, I could pre-process the state machine definition to double quote any jsonpath expression, but that would be quite a good effort, moreover, I'm not keen to disable validations.
Add support for Parallel state, as specified in the Amazon States Language spec: https://states-language.net/spec.html#parallel-state
Add validations for JSONPath queries. If a query is not valid, throw an error and end the step function execution
Add support for predefined error codes, as specified in the Amazon States Language spec: https://states-language.net/spec.html#appendix-a
At present, the spec does not prescribe any particular contents for the Context Object, so the Context Object in aws-local-stepfunctions
is simply an empty plain object that only gets modified when executing a Map
state, to support the $$.Map.Item.Index
and $$.Map.Item.Value
paths in the Parameters
field.
AWS Step Functions, however, documents that each execution gets passed a Context Object that includes some data regarding the state machine, the execution, and the current state being executed.
It would be nice to support passing custom data to the Context Object for each execution, so consumers have the ability to pass whatever data they need in the Context Object.
Thanks for this great lib!
We want to test the retry policy without waiting x seconds for each iteration. Is it possible to add an option to override the IntervalSeconds
property?
We can change this value in the test code as a workaround, but it would be fragile.
Add logging to better understand the behavior of the program, debug unexpected issues and provide messages to the user. Kind of similar to StepFunctions execution history in the AWS Console.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.