task_local context over context objects

- interner impls logically separate from API in orchid-base (default host interner still in base for testing)
- error reporting, logging, and a variety of other features passed down via context in extension, not yet in host to maintain library-ish profile, should consider options
- no global spawn mechanic, the host has a spawn function but extensions only get a stash for enqueuing async work in sync callbacks which is then explicitly, manually, and with strict order popped and awaited
- still deadlocks nondeterministically for some ungodly reason
This commit is contained in:
2026-01-01 14:54:29 +00:00
parent 06debb3636
commit 32d6237dc5
92 changed files with 2507 additions and 2223 deletions

View File

@@ -5,9 +5,10 @@ use std::ops::Add;
use std::rc::Rc;
use std::sync::Arc;
use futures::FutureExt;
use futures::future::join_all;
use itertools::Itertools;
use some_executor::task_local;
use task_local::task_local;
use crate::api;
use crate::interner::{IStr, es, is};
@@ -237,7 +238,19 @@ task_local! {
static REPORTER: Reporter;
}
pub async fn with_reporter<T>(fut: impl Future<Output = OrcRes<T>>) -> OrcRes<T> {
/// Run the future with a new reporter, and return all errors reported within.
///
/// If your future returns [OrcRes], see [try_with_reporter]
pub async fn with_reporter<T>(fut: impl Future<Output = T>) -> OrcRes<T> {
try_with_reporter(fut.map(Ok)).await
}
/// Run the future with a new reporter, and return all errors either returned or
/// reported by it
///
/// If your future may report errors but always returns an approximate value,
/// see [with_reporter]
pub async fn try_with_reporter<T>(fut: impl Future<Output = OrcRes<T>>) -> OrcRes<T> {
let rep = Reporter::default();
let res = REPORTER.scope(rep.clone(), fut).await;
let errors = rep.errors.take();
@@ -249,9 +262,8 @@ pub async fn with_reporter<T>(fut: impl Future<Output = OrcRes<T>>) -> OrcRes<T>
}
pub async fn is_erroring() -> bool {
REPORTER.with(|r| {
!r.expect("Sidechannel errors must be caught by a reporter").errors.borrow().is_empty()
})
(REPORTER.try_with(|r| !r.errors.borrow().is_empty()))
.expect("Sidechannel errors must be caught by a reporter")
}
/// Report an error that is fatal and prevents a correct output, but
@@ -259,11 +271,10 @@ pub async fn is_erroring() -> bool {
/// This can be used for
pub fn report(e: impl Into<OrcErrv>) {
let errv = e.into();
REPORTER.with(|r| match r {
Some(r) => r.errors.borrow_mut().extend(errv),
None => panic!(
REPORTER.try_with(|r| r.errors.borrow_mut().extend(errv.clone())).unwrap_or_else(|_| {
panic!(
"Unhandled error! Sidechannel errors must be caught by an enclosing call to with_reporter.\n\
Error: {errv}",
),
Error: {errv}"
)
})
}