Skip to content

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:

flow
on> :checkout from @customer
  order moves to #awaiting_payment       // action
  emit :payment_request to @payment      // action
  $checkout_time becomes now             // action

Types of Actions

State Transitions

Move the machine to a new state:

flow
order moves to #pending
order transitions to #approved
order enters #processing
order becomes #completed

All these keywords are equivalent - use what reads best.

Context Updates

Modify machine data:

flow
$total becomes 100
$total increases by 25
$items adds "Laptop"
$status becomes "active"

Event Emissions

Send events to other machines:

flow
emit :payment_request to @payment
emit :notification to @customer
emit :log_event to @audit

With Data

flow
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:

flow
send confirmation email
update inventory counts
notify warehouse team
calculate shipping cost
validate credit card

Action Execution Order

Actions execute in order, top to bottom:

flow
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             // 5th

Actions Under Guards

Actions only execute if their guard passes:

flow
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 guard

Multiple Actions

Group related actions together:

flow
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 @analytics

Conditional Action Groups

Different actions based on conditions:

flow
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 @customer

Entry and Exit Actions

Actions can be tied to entering or exiting states:

flow
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 timer

Async vs Sync

Event handlers execute synchronously, but emit is asynchronous:

flow
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 now

The emit puts an event on a queue - the target machine processes it later.

Action Patterns

Logging and Auditing

flow
on> :sensitive_action from @user
  log action attempt
  ? user is authorized
    perform action
    log action success
  otherwise
    log action denied
    emit :security_alert to @admin

Chained Actions

flow
on> :submit_order from @customer
  validate order
  calculate final price
  apply discounts
  reserve inventory
  create invoice
  order moves to #submitted
  emit :order_submitted to @customer

Compensating Actions

flow
on :payment_failed from @payment
  release reserved inventory
  cancel pending shipment
  restore cart state
  order moves to #cart
  emit :checkout_cancelled to @customer

Actions and Context

Actions often update context:

flow
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 + $tax

Natural Language Freedom

Write actions in natural, readable language:

flow
on> :order_shipped from @warehouse
  update tracking information
  send shipment notification to customer
  record shipment in analytics
  order moves to #shipped

These will be bound to PHP (or other language) implementations.

Built-in Actions

Some actions are handled automatically:

ActionEffect
$var becomes valueSet context variable
$var increases by nArithmetic addition
$var decreases by nArithmetic subtraction
$var adds itemAdd to collection
$var removes itemRemove from collection
$var clearsClear collection
X moves to #stateState transition
emit :event to @actorSend event

Custom actions require bindings.

Best Practices

Keep Actions Focused

flow
// 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 sending

Use Descriptive Names

flow
// Good
send order confirmation email
update customer loyalty points
record transaction in ledger

// Avoid
do email thing
update stuff
record

Order Matters

flow
// 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

Released under the MIT License.