flow: try-catch combinator — reify raised exceptions + 6 tests
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 34s
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 34s
(try-catch node handler) runs node; on a raised exception calls (handler error) with the reified error via Scheme guard, returns the handler value. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,10 +1,10 @@
|
|||||||
{
|
{
|
||||||
"total": 30,
|
"total": 36,
|
||||||
"passed": 30,
|
"passed": 36,
|
||||||
"failed": 0,
|
"failed": 0,
|
||||||
"suites": {
|
"suites": {
|
||||||
"basic": { "passed": 18, "total": 18 },
|
"basic": { "passed": 18, "total": 18 },
|
||||||
"control": { "passed": 12, "total": 12 }
|
"control": { "passed": 18, "total": 18 }
|
||||||
},
|
},
|
||||||
"phases": { "phase1": "done", "phase2": "in-progress" }
|
"phases": { "phase1": "done", "phase2": "in-progress" }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# flow-on-sx Scoreboard
|
# flow-on-sx Scoreboard
|
||||||
|
|
||||||
**All tests pass: 30 / 30 across 2 suites.**
|
**All tests pass: 36 / 36 across 2 suites.**
|
||||||
|
|
||||||
`bash lib/flow/conformance.sh`
|
`bash lib/flow/conformance.sh`
|
||||||
|
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
| Suite | Passing | Covers |
|
| Suite | Passing | Covers |
|
||||||
|-------|--------:|--------|
|
|-------|--------:|--------|
|
||||||
| basic | 18 | Phase 1: single nodes, linear sequence, data-flow threading, defflow, parallel fan/join, nested composition, publish-shaped flow |
|
| basic | 18 | Phase 1: single nodes, linear sequence, data-flow threading, defflow, parallel fan/join, nested composition, publish-shaped flow |
|
||||||
| control | 12 | Phase 2: `branch` conditional (6); error model `fail`/`failed?`/`fail-reason` failure values that flow as data (6) |
|
| control | 18 | Phase 2: `branch` (6); error model `fail`/`failed?`/`fail-reason` (6); `try-catch` reifying raised exceptions (6) |
|
||||||
|
|
||||||
## Architecture
|
## Architecture
|
||||||
|
|
||||||
@@ -36,6 +36,6 @@ capture the flow continuation directly.
|
|||||||
## Phases
|
## Phases
|
||||||
|
|
||||||
- [x] Phase 1 — Declarative DAG + sequential execution (combinators + 18 tests, `flow/start`)
|
- [x] Phase 1 — Declarative DAG + sequential execution (combinators + 18 tests, `flow/start`)
|
||||||
- [~] Phase 2 — Control flow + error handling (`branch`, error model done)
|
- [~] Phase 2 — Control flow + error handling (`branch`, error model, `try-catch` done)
|
||||||
- [ ] Phase 3 — Suspend / resume (the showcase)
|
- [ ] Phase 3 — Suspend / resume (the showcase)
|
||||||
- [ ] Phase 4 — Distributed nodes via fed-sx
|
- [ ] Phase 4 — Distributed nodes via fed-sx
|
||||||
|
|||||||
@@ -22,6 +22,8 @@
|
|||||||
;; (fail reason) — make an explicit failure value (data, not an exception)
|
;; (fail reason) — make an explicit failure value (data, not an exception)
|
||||||
;; (failed? x) — is x a failure value?
|
;; (failed? x) — is x a failure value?
|
||||||
;; (fail-reason x) — the reason carried by a failure value
|
;; (fail-reason x) — the reason carried by a failure value
|
||||||
|
;; (try-catch node handler) — run node; if it raises, call (handler error)
|
||||||
|
;; with the reified error and return the handler's value
|
||||||
|
|
||||||
(define
|
(define
|
||||||
flow-combinators-src
|
flow-combinators-src
|
||||||
@@ -29,7 +31,7 @@
|
|||||||
|
|
||||||
(define
|
(define
|
||||||
flow-control-src
|
flow-control-src
|
||||||
"(define (branch pred then else)\n (lambda (input) (if (pred input) (then input) (else input))))\n (define (fail reason) (list (quote flow-fail) reason))\n (define (failed? x) (and (pair? x) (eq? (car x) (quote flow-fail))))\n (define (fail-reason x) (car (cdr x)))")
|
"(define (branch pred then else)\n (lambda (input) (if (pred input) (then input) (else input))))\n (define (fail reason) (list (quote flow-fail) reason))\n (define (failed? x) (and (pair? x) (eq? (car x) (quote flow-fail))))\n (define (fail-reason x) (car (cdr x)))\n (define (try-catch node handler)\n (lambda (input) (guard (e (#t (handler e))) (node input))))")
|
||||||
|
|
||||||
(define
|
(define
|
||||||
flow-load-combinators!
|
flow-load-combinators!
|
||||||
|
|||||||
@@ -78,4 +78,34 @@
|
|||||||
"(defflow guarded (sequence (lambda (s) (if (>= (string-length s) 3) (string-length s) (fail (quote too-short)))) (branch failed? (lambda (f) (list (quote recovered) (fail-reason f))) (lambda (n) (list (quote ok) n))))) (flow/start guarded \"hi\")")
|
"(defflow guarded (sequence (lambda (s) (if (>= (string-length s) 3) (string-length s) (fail (quote too-short)))) (branch failed? (lambda (f) (list (quote recovered) (fail-reason f))) (lambda (n) (list (quote ok) n))))) (flow/start guarded \"hi\")")
|
||||||
(list "recovered" "too-short"))
|
(list "recovered" "too-short"))
|
||||||
|
|
||||||
|
;; ── try-catch — reify raised exceptions ─────────────────────────
|
||||||
|
(flow-ctl-test
|
||||||
|
"try-catch: no exception returns node result"
|
||||||
|
(flow-c "(flow/start (try-catch (lambda (x) (* x 2)) (lambda (e) -1)) 5)")
|
||||||
|
10)
|
||||||
|
(flow-ctl-test
|
||||||
|
"try-catch: handler runs on raise"
|
||||||
|
(flow-c
|
||||||
|
"(flow/start (try-catch (lambda (x) (raise (quote boom))) (flow-const 99)) 1)")
|
||||||
|
99)
|
||||||
|
(flow-ctl-test
|
||||||
|
"try-catch: handler receives the reified error"
|
||||||
|
(flow-c "(flow/start (try-catch (lambda (x) (raise 42)) (lambda (e) e)) 0)")
|
||||||
|
42)
|
||||||
|
(flow-ctl-test
|
||||||
|
"try-catch: catches exception from deep inside a sequence"
|
||||||
|
(flow-c
|
||||||
|
"(flow/start (try-catch (sequence (lambda (x) (+ x 1)) (lambda (x) (raise (quote deep)))) (flow-const -99)) 5)")
|
||||||
|
-99)
|
||||||
|
(flow-ctl-test
|
||||||
|
"try-catch: handler may convert to a failure value"
|
||||||
|
(flow-c
|
||||||
|
"(failed? (flow/start (try-catch (lambda (x) (raise (quote bad))) (lambda (e) (fail e))) 0))")
|
||||||
|
true)
|
||||||
|
(flow-ctl-test
|
||||||
|
"try-catch: composes — recover then continue"
|
||||||
|
(flow-c
|
||||||
|
"(flow/start (sequence (try-catch (lambda (x) (raise (quote x))) (flow-const 10)) (lambda (n) (* n 5))) 0)")
|
||||||
|
50)
|
||||||
|
|
||||||
(define flow-ctl-tests-run! (fn () {:total (+ flow-ctl-pass flow-ctl-fail) :passed flow-ctl-pass :failed flow-ctl-fail :fails flow-ctl-fails}))
|
(define flow-ctl-tests-run! (fn () {:total (+ flow-ctl-pass flow-ctl-fail) :passed flow-ctl-pass :failed flow-ctl-fail :fails flow-ctl-fails}))
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ federation extension via fed-sx for remote-node execution.
|
|||||||
|
|
||||||
## Status (rolling)
|
## Status (rolling)
|
||||||
|
|
||||||
`bash lib/flow/conformance.sh` → **30/30** (Phase 1 done; Phase 2 in progress)
|
`bash lib/flow/conformance.sh` → **36/36** (Phase 1 done; Phase 2 in progress)
|
||||||
|
|
||||||
## Ground rules
|
## Ground rules
|
||||||
|
|
||||||
@@ -79,7 +79,8 @@ lib/flow/spec.sx lib/flow/runtime.sx lib/flow/store.sx
|
|||||||
Scheme special form). `(branch pred then else)` — 6 tests.
|
Scheme special form). `(branch pred then else)` — 6 tests.
|
||||||
- [ ] `retry n [backoff]` — re-runs node up to n times on exception
|
- [ ] `retry n [backoff]` — re-runs node up to n times on exception
|
||||||
- [ ] `timeout ms` — bounds node execution
|
- [ ] `timeout ms` — bounds node execution
|
||||||
- [ ] `try-catch` — exception handler with reified error
|
- [x] `try-catch` — exception handler with reified error: `(try-catch node handler)`
|
||||||
|
runs node; on raise, calls `(handler error)` and returns its value. 6 tests.
|
||||||
- [x] error model — exceptions vs explicit `(fail reason)` results: `fail`/`failed?`/
|
- [x] error model — exceptions vs explicit `(fail reason)` results: `fail`/`failed?`/
|
||||||
`fail-reason` produce/inspect failure values that flow downstream as data
|
`fail-reason` produce/inspect failure values that flow downstream as data
|
||||||
(distinct from raised exceptions caught by retry/try-catch). 6 tests.
|
(distinct from raised exceptions caught by retry/try-catch). 6 tests.
|
||||||
|
|||||||
Reference in New Issue
Block a user