V.4 Цепочки и конкурентность
const PROFILE_DEADLINE = 300ms
// Цепочка: либо выполняется целиком, либо возвращает первую необработанную ошибку
fn profilePage(id: UserId) -> Page | NotFound | NetError net {
await Users.get(id) // шаг 1: rpc; при NotFound цепочка прерывается
-> (Orders.recentFor(it.id), Recs.forUser(it.id)) // шаг 2: шаг-кортеж = два запроса параллельно; it — результат шага 1
-> (orders, recs) => Page{ orders, recs } // шаг 3: лямбда разбирает кортеж
!> Timeout => Page.empty() // при таймауте любого шага слева — пустая страница
within PROFILE_DEADLINE // общий дедлайн на всю цепочку
}
fn crawl(urls: List<Url>) -> List<Doc> | HttpError | NetError net {
// Task.of откладывает вызов; all запускает все задачи параллельно
// и отменяет остальные при первой ошибке
let pages = all(urls.map(u => Task.of { Http.get(u) }))?
pages.map(.toDoc()) // .toDoc() — сокращение для p => p.toDoc()
}
// Канал: читаем задания, пока отправители живы, и отправляем отчёты
fn worker(jobs: Receiver<Job>, results: Sender<Report>) -> () | Closed net {
while let job? = jobs.recv().ok() { // job? — образец «не none»; цикл кончается, когда канал закрыт
results.send(process(job))? // send ждёт, если буфер results заполнен
}
}Исходник: docs/spec/oxl-standard.md