v4_concurrency.oxl
V.4 with local stand-ins for the services (rpc is stage 3)
// V.4 with local stand-ins for the services (rpc is stage 3)
const PROFILE_DEADLINE = 300ms
type UserId = distinct i64
@error data NotFound { id: i64 }
data User { id: UserId; name: str }
data Order { total: i64 }
data Page { orders: List<Order>; recs: List<str> }
impl Page { static fn empty() -> Page => Page{ orders: [], recs: [] } }
fn getUser(id: UserId) -> User | NotFound | Timeout time {
sleep(5ms)
if id.raw == 0 { fail NotFound{ id: 0 } }
User{ id, name: "ann" }
}
fn recentFor(id: UserId) -> List<Order> | Timeout time {
sleep(20ms)
[Order{ total: 100 }, Order{ total: 250 }]
}
fn forUser(id: UserId) -> List<str> | Timeout time {
sleep(if id.raw == 2 { 2s } else { 10ms })
["book", "pen"]
}
fn profilePage(id: UserId) -> Page | NotFound | Timeout time {
await getUser(id)
-> (recentFor(it.id), forUser(it.id))
-> (orders, recs) => Page{ orders, recs }
!> Timeout => Page.empty()
within PROFILE_DEADLINE
}
data Job { n: i64 }
data Report { n: i64; sq: i64 }
fn process(j: Job) -> Report => Report{ n: j.n, sq: j.n * j.n }
fn worker(jobs: Receiver<Job>, results: Sender<Report>) -> () | Closed {
while let job? = jobs.recv().ok() {
results.send(process(job))?
}
}
fn main() io, time {
match profilePage(UserId(1)) {
Page p => print("orders {p.orders.len()} recs {p.recs.len()}")
NotFound => print("not found")
Timeout => print("timeout")
}
match profilePage(UserId(0)) {
NotFound => print("not found")
_ => print("?")
}
let (jtx, jrx) = chan<Job>(cap: 4)
let (rtx, rrx) = chan<Report>(cap: 4)
let total = scope {
spawn worker(jrx, rtx)
for i in 1..=5 { _ = jtx.send(Job{ n: i }) }
drop(jtx)
var sum = 0
while let r? = rrx.recv().ok() { sum += r.sq }
sum
}
print("sum of squares {total}")
}Source: examples/v4_concurrency.oxl