Your Own Capabilities: When a call is refused
● Intermediate3 min
A refused call fails with Denied(reason), an ordinary error: match on it like any other.
type PayError = Declined | Unavailable | Denied(reason: String)
capability Payments {
fn refund(order: Int, amount: Int) ! PayError
}
type Bank: Payments {
fn refund(self, order: Int, amount: Int) ! PayError {
print("refunded {amount} on order {order}")
}
}
agent Refunder {
can Payments.refund
limit Payments.refund {
amount <= 500
}
on refund(order: Int, amount: Int) ! PayError {
try Payments.refund(order, amount)
}
}
fn main() {
const bot = Refunder.start(Payments: Bank())
for r in [(order: 1, amount: 200), (order: 2, amount: 900)] {
bot.refund(r.order, r.amount) catch e => match e {
PayError.Denied(reason) => print("order {r.order}: blocked, {reason}"),
PayError.Declined => print("order {r.order}: the bank said no"),
PayError.Unavailable => print("order {r.order}: try again later"),
_ => print("order {r.order}: {e}"),
}
}
}The program ran and printed:
kavach run own-refused.kav
refunded 200 on order 1order 2: blocked, limit broken: amount <= 500
The reason says what refused it: a broken limit, a person who said no, or no implementation. Handle Denied apart from the system's own errors, such as a declined card or a bank that is down.
The _ arm is needed: a send can always fail with something else too, such as a panic in the handler.