Actions
Actions are what happens when an event is received and guards pass. They're written without any prefix - actions are the default line type.
Basic Actions
Actions are any line that isn't a guard (?), assertion (=), or keyword:
on> :checkout from @customer
order moves to #awaiting_payment // action
emit :payment_request to @payment // action
$checkout_time becomes now // actionTypes of Actions
State Transitions
Move the machine to a new state:
order moves to #pending
order transitions to #approved
order enters #processing
order becomes #completedAll these keywords are equivalent - use what reads best.
Context Updates
Modify machine data:
$total becomes 100
$total increases by 25
$items adds "Laptop"
$status becomes "active"Event Emissions
Send events to other machines:
emit :payment_request to @payment
emit :notification to @customer
emit :log_event to @auditWith Data
emit :payment_request to @payment
with $order_id, $total, $currency
emit :order_details to @warehouse
with:
| field | value |
| order_id | $order_id |
| items | $items |
| address | $address |Natural Language Actions
Any descriptive action that will be bound to code:
send confirmation email
update inventory counts
notify warehouse team
calculate shipping cost
validate credit cardAction Execution Order
Actions execute in order, top to bottom:
on> :checkout from @customer
validate cart // 1st
calculate totals // 2nd
order moves to #awaiting_payment // 3rd
emit :payment_request to @payment // 4th
send checkout confirmation // 5thActions Under Guards
Actions only execute if their guard passes:
on> :checkout from @customer
? cart is not empty
order moves to #awaiting_payment // Only if guard passes
emit :payment_request to @payment // Only if guard passes
? cart is empty
emit :empty_cart_error to @customer // Different guardMultiple Actions
Group related actions together:
on> :complete_order from @system
order moves to #completed
$completed_at becomes now
$status becomes "fulfilled"
emit :order_completed to @customer
emit :update_inventory to @warehouse
emit :record_sale to @analyticsConditional Action Groups
Different actions based on conditions:
on> :process_payment from @payment
? payment is successful
order moves to #paid
$paid_at becomes now
emit :payment_confirmed to @customer
emit :prepare_shipment to @warehouse
? payment is declined
order moves to #payment_failed
$failure_reason becomes $decline_reason
emit :payment_failed to @customer
otherwise
order moves to #payment_pending
emit :payment_retry to @customerEntry and Exit Actions
Actions can be tied to entering or exiting states:
on> :checkout from @customer
// Exit actions from current state
log exit from cart state
// Transition
order moves to #awaiting_payment
// Entry actions for new state
$entered_awaiting_at becomes now
start payment timeout timerAsync vs Sync
Event handlers execute synchronously, but emit is asynchronous:
on> :checkout from @customer
validate cart // sync - happens now
order moves to #awaiting_payment // sync - happens now
emit :payment_request to @payment // async - queued for later
$status becomes "waiting" // sync - happens nowThe emit puts an event on a queue - the target machine processes it later.
Action Patterns
Logging and Auditing
on> :sensitive_action from @user
log action attempt
? user is authorized
perform action
log action success
otherwise
log action denied
emit :security_alert to @adminChained Actions
on> :submit_order from @customer
validate order
calculate final price
apply discounts
reserve inventory
create invoice
order moves to #submitted
emit :order_submitted to @customerCompensating Actions
on :payment_failed from @payment
release reserved inventory
cancel pending shipment
restore cart state
order moves to #cart
emit :checkout_cancelled to @customerActions and Context
Actions often update context:
on> :add_item from @customer
// Update multiple context variables
$items adds $item
$item_count increases by 1
$subtotal increases by $item.price
$tax becomes $subtotal * 0.1
$total becomes $subtotal + $taxNatural Language Freedom
Write actions in natural, readable language:
on> :order_shipped from @warehouse
update tracking information
send shipment notification to customer
record shipment in analytics
order moves to #shippedThese will be bound to PHP (or other language) implementations.
Built-in Actions
Some actions are handled automatically:
| Action | Effect |
|---|---|
$var becomes value | Set context variable |
$var increases by n | Arithmetic addition |
$var decreases by n | Arithmetic subtraction |
$var adds item | Add to collection |
$var removes item | Remove from collection |
$var clears | Clear collection |
X moves to #state | State transition |
emit :event to @actor | Send event |
Custom actions require bindings.
Best Practices
Keep Actions Focused
// Good - focused actions
on> :checkout from @customer
validate cart
calculate totals
order moves to #checkout
emit :begin_payment to @payment
// Avoid - too much in one place
on> :checkout from @customer
do everything for checkout including validation
and price calculation and inventory check
and payment processing and notification sendingUse Descriptive Names
// Good
send order confirmation email
update customer loyalty points
record transaction in ledger
// Avoid
do email thing
update stuff
recordOrder Matters
// Logical order
on> :refund from @admin
validate refund request // 1. Validate first
calculate refund amount // 2. Calculate
process refund to payment method // 3. Process
update order status // 4. Update state
order moves to #refunded // 5. Transition
emit :refund_complete to @customer // 6. Notify