I'm proposing a simple DSL for workflows. Something along the following lines.
state WaitForOrder
leave
when OrderIsCreated
when BelowApprovalThreshold
try WaitForShipment
else
try WaitForApproval
state WaitForShipment
on entry
SendAcceptanceEmail
CreateShippingRequest
leave
when ShipmentComplete
try OrderComplete
when ShipmentCancelled
try OrderCancelled
when OneWeekElapsed
try WaitForShipment
with SendShipmentReminder
state WaitForApproval
on entry
CreateApprovalRequest
leave
when Approved
try WaitForShipment
when Denied
try OrderCancelled
state OrderComplete
on entry
CompleteWorkflow
state OrderCancelled
on entry
CancelOrder
CompleteWorkflow
// **********************************
// *********** CONDITIONS ***********
// **********************************
condition OneWeekElapsed
as ElapsedTimeCondition {
1 week
}
condition BelowApprovalThreshold
as RulesCondition {
let order = Http.getWithCache("/api/orders/{order.id}");
let approvalThreshold = Configuration.get("OrderApprovalThreshold");
if (order.price * order.quantity > approvalThreshold) {
return false;
}
return true;
}
condition OrderIsCreated
as EntityIdCondition {
EntityId matches order.id
Activity is "Created"
}
condition ShipmentCancelled
as EntityIdCondition {
EntityId matches shipment.id
Activity is "ShipmentCancelled"
}
condition Approved
as EntityIdCondition {
EntityId matches approval.id
Activity is "Approved"
}
condition Denied
as EntityIdCondition {
EntityId matches approval.id
Activity is "Denied"
}
condition ShipmentComplete
as EntityIdCondition {
EntityId matches shipment.id
Activity is "ShipmentComplete"
}
// *******************************
// *********** ACTIONS ***********
// *******************************
action SendShipmentReminder
as RulesAction {
let shippingRequest = Http.getWithCache("/api/shipping/request/{shipment.id}");
let routing = {
from: "noreply@bigcorp.com",
to: "shipping@bigcorp.com",
subject: "No response to shipment request {shipment.id}"
};
Email.send(
routing,
"/email/shippingrequestremindertemplate",
order)
}
action SendAcceptanceEmail
as RulesAction {
let order = Http.getWithCache("/api/orders/{order.id}");
let routing = {
from: "noreply@bigcorp.com",
to: order.customer.email,
subject: "Order for {order.product} accepted"
};
Email.send(
routing,
"/email/orderacceptancetemplate",
order)
}
action CreateShippingRequest
as RulesAction {
let order = Http.getWithCache("/api/orders/{order.id}");
let result = Http.post("/api/shipping/request", order);
// add the shipment id to the instance context
Workflow.updateCurrentInstance([
{ "shipment.id": result.id }
]);
// create a new workflow instance for the shipment request
let shippingInstanceContext = {
"request.id", result.id,
"order.id", order.id
};
Workflow.createInstance("/orderworkflows/ordershipment", shippingInstanceContext);
}
action CreateApprovalRequest
as RulesAction {
let order = Http.getWithCache("/api/orders/{order.id}");
let result = Http.post("/api/approvals/request", order);
// add the approval id to the instance context
Workflow.updateCurrentInstance([
{ "approval.id": result.id }
]);
// create a new workflow instance for the approval request
let approvalInstanceContext = {
"approval.id", result.id,
"order.id", order.id
};
Workflow.createInstance("/orderworkflows/orderapproval", approvalInstanceContext);
}
action CancelOrder
as RulesAction {
let result = Http.post("/api/order/cancel/{order.id}", { reason: "Shipping failed." });
// create a new workflow instance for the cancellation workflow
let cancellationInstanceContext = {
"cancellationrequest.id", result.id,
"order.id", order.id
};
Workflow.createInstance("/orderworkflows/ordercancellation", cancellationInstanceContext);
}
action CompleteWorkflow
as RulesAction {
Workflow.completeCurrentInstance();
}
I'm proposing a simple DSL for workflows. Something along the following lines.