flowreview v1examples/review/temporal/review.flow · dandori doc
Jev scores an application and says how sure it is, and a rule decides whether the verdict is acted on at once or goes to a person for approval, due by 17:00 on the third business day after it comes in: approving at once asks more certainty than rejecting at once. Written for Temporal: the scoring is an activity dandori writes, which calls Jev with TypeSafe's key (TYPESAFE_API_KEY) on the workers of its own task queue, which may be written in another language, and so does the notice, an activity you write; the rule and the date of the approval run in the worker of the workflow; the approver's tool answers the callback by the update the generated client sends
flow| Line | Call | Calls | Retries | Timeout | When it fails |
|---|---|---|---|---|---|
| 51 | r = score(…) | jev · jev-1.13.0 | 2 times every 10 seconds (busy, overloaded) | 10 seconds | busy, overloaded, timeout, failure → line 52 |
| 53 | d = policy(…) | rule review_policy.rule | 2 times, after 1 second and 2 (failure, timeout) | 10 seconds | timeout, failure → the workflow fails |
| 57 | due = approvals.due(…) | the date due of approval_terms.cal | 2 times, after 1 second and 2 (failure, timeout) | 10 seconds | timeout, failure → the workflow fails |
| 58 | a = ask_for_approval(…) | a task you write, answered by a callback | — | 1 minute to hand the id on, then until due.at | timeout → line 59failure → the workflow fails |
| 60 | notify(…) | a task you write, idempotent | — | — | timeout, failure → the workflow fails |
| 62 | notify(…) | a task you write, idempotent | — | — | timeout, failure → the workflow fails |
| Line | End |
|---|---|
| 52 | fail Unscorable "Could not score application {application.id}" |
| 59 | fail NoAnswer "No approval by 17:00 on the third business day" |
| 61 | succeed verdict = approve |
| 63 | succeed verdict = r.verdict |
Pick a step to see what the checker knows there. Pick a scenario on the left to light up the way its run goes; the number beside a step is how often the run passes it.
review v1Jev scores an application and says how sure it is, and a rule decides whether the verdict is acted on at once or goes to a person for approval, due by 17:00 on the third business day after it comes in: approving at once asks more certainty than rejecting at once. Written for Temporal: the scoring is an activity dandori writes, which calls Jev with TypeSafe's key (TYPESAFE_API_KEY) on the workers of its own task queue, which may be written in another language, and so does the notice, an activity you write; the rule and the date of the approval run in the worker of the workflow; the approver's tool answers the callback by the update the generated client sends
application: Applicationverdict: policy.verdictexamples/review/temporal/review.flowr = score(…) line 5151 let r = score(purpose: application.purpose) 52 on failure => fail Unscorable "Could not score application {application.id}"
jev · jev-1.13.0busy, overloaded, timeout, failure → line 5225 # Jev places what the applicant wrote on the scale of verdicts, from the lowest level, and how 26 # sure it is of the verdict comes as a rate, for the rule to weigh. 27 task score(purpose: string) -> Score 28 jev 29 verdict score "How clearly is the money for running the business?" 30 reject "It is for something personal or speculative, or against the law" 31 hold "It is for the business, but the statement leaves unclear what it pays for" 32 approve "It pays for a named part of running the business, such as stock, equipment, staff or premises" 33 sure confidence of verdict 34 model "jev-1.13.0" 35 queue "scoring" 36 errors busy = 429, overloaded = 529 37 retry 2 times every 10 seconds on busy, overloaded 38 timeout 10 seconds
fail Unscorable line 52 52 on failure => fail Unscorable "Could not score application {application.id}"
d = policy(…) line 53 53 let d = policy(verdict: r.verdict, sure: r.sure)
review_policy.ruletimeout, failure → the workflow fails 4 use rule policy from "../rules/review_policy.rule"
match d.decision line 5454 match d.decision 55 approve, reject => pass 56 ask =>
due = approvals.due(…) line 57 57 let due = approvals.due(received: now)
due of approval_terms.caltimeout, failure → the workflow fails 5 use dates approvals from "../dates/approval_terms.cal"
a = ask_for_approval(…) line 5858 let a = ask_for_approval(application_id: application.id, amount: application.amount, sure: r.sure, by: due.at) 59 on timeout => fail NoAnswer "No approval by 17:00 on the third business day"
due.attimeout → line 59failure → the workflow fails40 # Someone approves in a tool of their own, and the answer comes back with the callback's id. The 41 # approver is told when the approval is due, and the wait ends then. 42 task ask_for_approval(application_id: string, amount: int, sure: rate[step 1%], by: timestamp) -> Approval 43 callback 44 timeout until by
fail NoAnswer line 59 59 on timeout => fail NoAnswer "No approval by 17:00 on the third business day"
notify(…) line 60 60 notify(application_id: application.id, text: "{a.approver} approved application {application.id}")
idempotenttimeout, failure → the workflow fails46 task notify(application_id: string, text: string) 47 queue "notify" 48 idempotent
succeed verdict = approve line 61 61 succeed verdict = approve
notify(…) line 62 62 notify(application_id: application.id, text: "Application {application.id} was reviewed: {r.verdict}")
idempotenttimeout, failure → the workflow fails46 task notify(application_id: string, text: string) 47 queue "notify" 48 idempotent
succeed verdict = r.verdict line 63 63 succeed verdict = r.verdict
end: succeedsThe flow runs to its end, and the workflow succeeds.
r = score(…) okd = policy(…) okmatch d.decision → approve, rejectnotify(…) oksucceed verdict = r.verdictr = score(…) failure → on failurefail Unscorabler = score(…) busy okd = policy(…) failure failure failure → not handled herer = score(…) okr = score(…) okd = policy(…) okr = score(…) okd = policy(…) okmatch d.decision → approve, rejectnotify(…) failure → not handled herer = score(…) okd = policy(…) okmatch d.decision → askdue = approvals.due(…) oka = ask_for_approval(…) oknotify(…) oksucceed verdict = approver = score(…) busy okd = policy(…) okmatch d.decision → askdue = approvals.due(…) failure failure failure → not handled herer = score(…) okd = policy(…) okmatch d.decision → askdue = approvals.due(…) okr = score(…) okd = policy(…) okmatch d.decision → askdue = approvals.due(…) oka = ask_for_approval(…) timeout → on timeoutfail NoAnswerr = score(…) okd = policy(…) okmatch d.decision → askdue = approvals.due(…) oka = ask_for_approval(…) failure → not handled herer = score(…) okd = policy(…) okmatch d.decision → askdue = approvals.due(…) oka = ask_for_approval(…) okr = score(…) okd = policy(…) okmatch d.decision → askdue = approvals.due(…) oka = ask_for_approval(…) oknotify(…) failure → not handled here