Patterns · 3 of 4

Procedure composition

Procedures can call other procedures. Pass parameters as a single object literal. The whole chain runs in one transaction.

Calling another procedure

proc get_balance(account_id) {
    let acc = find_one("accounts", {_id: account_id})
    if acc == null { abort "not found" }
    return acc.balance
}

proc safe_withdraw(account_id, amount) {
    let bal = get_balance({account_id: account_id})
    if bal < amount { abort "insufficient funds" }
    update("accounts", {_id: account_id}, {$inc: {balance: -amount}})
    return {ok: true, withdrawn: amount, remaining: bal - amount}
}

Composing reads

proc get_user(id)     { return find_one("users", {_id: id}) }
proc get_orders(uid)  { return find("orders", {user_id: uid}) }
proc get_addresses(uid) { return find("addresses", {user_id: uid}) }

proc user_profile(id) {
    let user      = get_user({id: id})
    let orders    = get_orders({uid: id})
    let addresses = get_addresses({uid: id})
    return {user: user, orders: orders, addresses: addresses}
}

Composing writes

proc charge(account_id, amount) {
    update("accounts", {_id: account_id}, {$inc: {balance: -amount}})
    insert("ledger", {account_id: account_id, type: "charge", amount: amount})
    return {ok: true}
}

proc credit(account_id, amount) {
    update("accounts", {_id: account_id}, {$inc: {balance: amount}})
    insert("ledger", {account_id: account_id, type: "credit", amount: amount})
    return {ok: true}
}

proc transfer(from, to, amount) {
    charge({account_id: from, amount: amount})
    credit({account_id: to,   amount: amount})
    return {ok: true}
}

Composing validation

proc require_active(user_id) {
    let u = find_one("users", {_id: user_id})
    if u == null     { abort "user not found" }
    if !u.active     { abort "user not active" }
    return u
}

proc post_message(user_id, text) {
    require_active({user_id: user_id})
    insert("messages", {user_id: user_id, text: text})
    return {ok: true}
}

proc upload_file(user_id, size) {
    require_active({user_id: user_id})
    insert("files", {user_id: user_id, size: size})
    return {ok: true}
}

Building a service surface

proc account_actions(action, params) {
    if action == "create"   { return create_account(params) }
    if action == "freeze"   { return freeze_account(params) }
    if action == "unfreeze" { return unfreeze_account(params) }
    if action == "close"    { return close_account(params) }
    abort "unknown action"
}
Note: A called procedure is just inlined — its steps run in the same transaction. There's no separate retry, no commit between calls.
Report Issue