This repository has an example of creating a simple workflow microservice with NestJS and WorkflowJS.
First of all need to clone this repository by following command.
git clone https://github.com/vhidvz/workflow-template.git
Then install the node dependencies with command cd workflow-template && npm ci
. after that, install the MongoDB community server by the following command in your terminal.
docker-compose up -d
To start and run the project type npm run start
, that's it...
Swagger UI is also exists and running on http://[::1]:3000/api if you need to understand better please look at the src/
app.workflow.ts file.
Create a flow by posting a request with plain data Hi
.
curl --request POST \
--url http://localhost:3000/flow \
--header 'Content-Type: application/json' \
--data '{
"global": "Hi"
}'
Response: base on the flow definition exclusive gateway approval_gateway
cannot automatically done, therefor workflow will pauses at this point.
{
"data": {
"global": "Hi",
"_id": "643fcfe30eaf231a283a539b"
},
"status": "paused",
"tokens": [
{
"id": "cc5c8c5baa370eec",
"history": [
{
"status": "completed",
"ref": "StartEvent_0do01j4",
"name": "start"
},
{
"status": "completed",
"ref": "Activity_0mra47f",
"name": "initial_task"
},
{
"status": "paused",
"ref": "Gateway_0az0yjr",
"name": "approval_gateway"
}
]
}
],
"_id": "643fcfe30eaf231a283a539a",
"__v": 0
}
Find a flow by mongo id with the following GET
request.
curl --request GET \
--url http://localhost:3000/flow/643fcfe30eaf231a283a539a
Response: it must be same as the previous result.
Resume the flow by posting a PATCH
request with no
response by user.
curl -X 'PATCH' \
'http://[::1]:3000/flow/643fcfe30eaf231a283a539a/approval_gateway' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"local": "no"
}'
Response: because of some_task
is a user task at this state based on diagram we need to pause flow, therefor another request needed to complete this task.
{
"_id": "643fcfe30eaf231a283a539a",
"data": {
"global": "Hi, Hello no!",
"_id": "643fcfe30eaf231a283a539b"
},
"status": "paused",
"tokens": [
{
"id": "cc5c8c5baa370eec",
"history": [
{
"ref": "StartEvent_0do01j4",
"status": "completed",
"value": null,
"name": "start"
},
{
"ref": "Activity_0mra47f",
"status": "completed",
"value": null,
"name": "initial_task"
},
{
"ref": "Gateway_0az0yjr",
"status": "completed",
"value": {
"local": "no"
},
"name": "approval_gateway"
},
{
"ref": "Activity_1v0hfx6",
"status": "paused",
"value": null,
"name": "some_task"
}
]
}
],
"__v": 0
}
Finishing flow by resuming task some_task
.
curl -X 'PATCH' \
'http://[::1]:3000/flow/643fcfe30eaf231a283a539a/some_task' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"local": "done"
}'
Response: status of context is terminated and could not resume again.
{
"_id": "643fcfe30eaf231a283a539a",
"data": {
"global": "Hi, Hello no!, received a value from previous task(some value(done) to end event.)",
"_id": "643fcfe30eaf231a283a539b"
},
"status": "terminated",
"tokens": [
{
"id": "cc5c8c5baa370eec",
"history": [
{
"ref": "StartEvent_0do01j4",
"status": "completed",
"value": null,
"name": "start"
},
{
"ref": "Activity_0mra47f",
"status": "completed",
"value": null,
"name": "initial_task"
},
{
"ref": "Gateway_0az0yjr",
"status": "completed",
"value": {
"local": "no"
},
"name": "approval_gateway"
},
{
"ref": "Activity_1v0hfx6",
"status": "completed",
"value": {
"local": "done"
},
"name": "some_task"
},
{
"ref": "Event_13pwumb",
"status": "terminated",
"value": {
"local": "some value(done) to end event."
},
"name": "end"
}
]
}
],
"__v": 0
}
Create a flow by posting a request with plain data Hi
.
curl --request POST \
--url http://localhost:3000/flow \
--header 'Content-Type: application/json' \
--data '{
"global": "Hi"
}'
Response: would like be previous scenario but it has different id.
Resuming the flow by posting a PATCH
request with Vahid
response by user.
curl -X 'PATCH' \
'http://[::1]:3000/flow/643fe71df232a501b76cd7d6/approval_gateway' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"local": "Vahid"
}'
Response: because of another_task
is a user task at this state based on diagram we need to pause flow, therefor another request needed to complete this task.
{
"_id": "643fe71df232a501b76cd7d6",
"data": {
"global": "Hi, Hello Vahid!",
"_id": "643fe71df232a501b76cd7d7"
},
"status": "paused",
"tokens": [
{
"id": "9f053a81fa64e7fa",
"history": [
{
"ref": "StartEvent_0do01j4",
"status": "completed",
"value": null,
"name": "start"
},
{
"ref": "Activity_0mra47f",
"status": "completed",
"value": null,
"name": "initial_task"
},
{
"ref": "Gateway_0az0yjr",
"status": "completed",
"value": {
"local": "Vahid"
},
"name": "approval_gateway"
},
{
"ref": "Gateway_0du1v6k",
"status": "terminated",
"value": null,
"name": "parallel_gateway"
}
],
"locked": true
},
{
"id": "f44c569ffee96983",
"history": [
{
"ref": "Activity_1yl745l",
"status": "completed",
"value": null,
"name": "do_some_work"
},
{
"ref": "Gateway_0ll1i6q",
"status": "paused",
"value": null
}
],
"parent": "9f053a81fa64e7fa"
},
{
"id": "772454979815fdc1",
"history": [
{
"ref": "Activity_1mzlm3i",
"status": "paused",
"value": null,
"name": "another_task"
}
],
"parent": "9f053a81fa64e7fa"
}
],
"__v": 0
}
Resuming the flow by posting a PATCH
request with Finished Successfully
response by user.
curl -X 'PATCH' \
'http://[::1]:3000/flow/643fe71df232a501b76cd7d6/another_task' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"local": "Finished Successfully"
}'
Response: because of review
is a user task at this state based on diagram we need to pause flow, therefor another request needed to complete this task.
{
"_id": "643fe71df232a501b76cd7d6",
"data": {
"global": "Hi, Hello Vahid!",
"_id": "643fe71df232a501b76cd7d7"
},
"status": "paused",
"tokens": [
{
"id": "9f053a81fa64e7fa",
"history": [
{
"ref": "StartEvent_0do01j4",
"status": "completed",
"value": null,
"name": "start"
},
{
"ref": "Activity_0mra47f",
"status": "completed",
"value": null,
"name": "initial_task"
},
{
"ref": "Gateway_0az0yjr",
"status": "completed",
"value": {
"local": "Vahid"
},
"name": "approval_gateway"
},
{
"ref": "Gateway_0du1v6k",
"status": "terminated",
"value": null,
"name": "parallel_gateway"
}
],
"locked": true
},
{
"id": "f44c569ffee96983",
"history": [
{
"ref": "Activity_1yl745l",
"status": "completed",
"value": null,
"name": "do_some_work"
},
{
"ref": "Gateway_0ll1i6q",
"status": "terminated",
"value": null
}
],
"parent": "9f053a81fa64e7fa",
"locked": true
},
{
"id": "772454979815fdc1",
"history": [
{
"ref": "Activity_1mzlm3i",
"status": "completed",
"value": {
"local": "Finished Successfully"
},
"name": "another_task"
},
{
"ref": "Activity_1cqjzpt",
"status": "completed",
"value": null,
"name": "pay_money"
},
{
"ref": "Gateway_0ll1i6q",
"status": "terminated",
"value": null
}
],
"parent": "9f053a81fa64e7fa",
"locked": true
},
{
"id": "191b71808f807535",
"history": [
{
"ref": "Gateway_0ll1i6q",
"status": "completed",
"value": null
},
{
"ref": "Activity_0thx22h",
"status": "paused",
"value": null,
"name": "review"
}
]
}
],
"__v": 0
}
Finishing flow by resuming task review
.
curl -X 'PATCH' \
'http://[::1]:3000/flow/643fe71df232a501b76cd7d6/review' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"local": "review"
}'
Response: status of context is terminated and could not resume again.
{
"_id": "643fe71df232a501b76cd7d6",
"data": {
"global": "Hi, Hello Vahid!, received a value from previous task(review to end event.)",
"_id": "643fe71df232a501b76cd7d7"
},
"status": "terminated",
"tokens": [
{
"id": "9f053a81fa64e7fa",
"history": [
{
"ref": "StartEvent_0do01j4",
"status": "completed",
"value": null,
"name": "start"
},
{
"ref": "Activity_0mra47f",
"status": "completed",
"value": null,
"name": "initial_task"
},
{
"ref": "Gateway_0az0yjr",
"status": "completed",
"value": {
"local": "Vahid"
},
"name": "approval_gateway"
},
{
"ref": "Gateway_0du1v6k",
"status": "terminated",
"value": null,
"name": "parallel_gateway"
}
],
"locked": true
},
{
"id": "f44c569ffee96983",
"history": [
{
"ref": "Activity_1yl745l",
"status": "completed",
"value": null,
"name": "do_some_work"
},
{
"ref": "Gateway_0ll1i6q",
"status": "terminated",
"value": null
}
],
"parent": "9f053a81fa64e7fa",
"locked": true
},
{
"id": "772454979815fdc1",
"history": [
{
"ref": "Activity_1mzlm3i",
"status": "completed",
"value": {
"local": "Finished Successfully"
},
"name": "another_task"
},
{
"ref": "Activity_1cqjzpt",
"status": "completed",
"value": null,
"name": "pay_money"
},
{
"ref": "Gateway_0ll1i6q",
"status": "terminated",
"value": null
}
],
"parent": "9f053a81fa64e7fa",
"locked": true
},
{
"id": "191b71808f807535",
"history": [
{
"ref": "Gateway_0ll1i6q",
"status": "completed",
"value": null
},
{
"ref": "Activity_0thx22h",
"status": "completed",
"value": {
"local": "review"
},
"name": "review"
},
{
"ref": "Event_13pwumb",
"status": "terminated",
"value": {
"local": "review to end event."
},
"name": "end"
}
]
}
],
"__v": 0
}
This project is licensed under the MIT License - SEE the LICENSE file for details