completion.bend

bend-kit-http@0.38.2.0 · 43 lines · 8 definitions

1# Copied response completion data; successful host writes do not prove peer receipt.
2import Base
3
4type Outcome is Data:
5  HostAccepted{}
6  WriteFailed{code: U32, message: String}
7  IncompleteResponse{}
8
9type Completion<-D: Data> is Data:
10  Completion{payload: D, status: U32, outcome: Outcome}
11
12# Consumed inline while the admitted operation is still held.
13# Supported receipts capture Data only through receipt's typed factory and a
14# closed callback. Never hide affine dependencies in a disposable receipt.
15type Receipt is Type:
16  Unobserved{}
17  Observed{send: U32 -> Outcome -> IO(Unit)}
18
19def receipt.send(~D: Data, payload: D, +channel: Chan(Completion<D>), status: U32, outcome: Outcome) -> IO(Unit):
20  do IO<Unit>:
21    sent : Result<&1, &1, Completion<D>, Unit> <- Chan.send(Completion<D>, channel, Completion{payload, status, outcome})
22    return Unit{}
23
24def receipt(~D: Data, ~done: Completion<D> -> IO(Unit), payload: D) -> Receipt:
25  Observed{status => outcome => done(Completion{payload, status, outcome})}
26
27# The observer owns IO.join/explicit close, including when it receives later.
28# Closing before reception is disposal; it never carries affine resources.
29def open(~D: Data, payload: D) -> IO(Receipt & Chan(Completion<D>)):
30  do IO<Receipt & Chan(Completion<D>)>:
31    +channel : Chan(Completion<D>) <- Chan.new(Completion<D>, 1)
32    return (Observed{status => outcome => receipt.send(~D, payload, channel, status, outcome)}, channel)
33
34def report(receipt: Receipt, status: U32, outcome: Outcome) -> IO(Unit):
35  match receipt:
36    case Unobserved{}:
37      IO.pure(Unit, Unit{})
38    case Observed{send}:
39      send(status, outcome)
40
41# Explicit absence of a configured observer performs no logging or allocation.
42def ignore(status: U32, outcome: Outcome) -> IO(Unit):
43  IO.pure(Unit, Unit{})