teksilo_async/lib.rs
1// SPDX-License-Identifier: MPL-2.0
2// SPDX-FileCopyrightText: 2026 FernTech
3
4//! # teksilo-async — optional main-thread async executor for Teksilo
5//!
6//! Teksilo keeps the view layer synchronous: "async is the backend's concern."
7//! Most background→UI flows are best served by the reactive data path
8//! (`ctx.subscribe_event(...)` + `Signal::set`). This crate is the **opt-in**
9//! escape hatch for the cases that want *imperative* async — writing linear
10//! `async` / `.await` inside a handler, sequencing several awaits in one place.
11//!
12//! ```ignore
13//! use teksilo_async::{TeksiloAppBuilderAsyncExt, EventContextAsyncExt, spawn_blocking};
14//!
15//! TeksiloAppBuilder::new().install_async() /* ... */ .run();
16//!
17//! // inside a handler:
18//! let status = self.status.clone(); // Signal<Status> (Rc clone)
19//! ctx.spawn_local(async move {
20//! status.set(Status::Loading);
21//! let bytes = spawn_blocking(move || std::fs::read(path)).await;
22//! status.set(Status::from(bytes)); // resume on the UI thread → set Signal
23//! })
24//! .detach();
25//! ```
26//!
27//! ## Model
28//!
29//! - The executor is single-threaded and `!Send`; `spawn_local` futures live on
30//! the UI thread and capture `Rc`-based `Signal`s, mutating them on resume.
31//! There is no `EventContext` after `.await` (it is borrow-transient), so UI
32//! updates flow through owned handles (Signals) — the reactive model.
33//! - For a one-shot ambient op after the work finishes (`open_window`,
34//! `send_intent`, …), [`spawn_local_with`](EventContextAsyncExt::spawn_local_with)
35//! delivers the result to a callback with a *fresh* `EventContext`.
36//! - [`spawn_blocking`] offloads blocking work to an OS thread and awaits the
37//! result — no async runtime required.
38//!
39//! The executor is driven once per event-loop turn via the async-agnostic
40//! [`on_loop_tick`](teksilo_app::TeksiloAppBuilder::on_loop_tick) hook; it
41//! sleeps (zero idle CPU) until a task is woken, including from a
42//! `spawn_blocking` worker thread.
43//!
44//! `teksilo-tokio` / `teksilo-async-std` build on this crate to add reactor
45//! support so native-ecosystem futures (`tokio::time`, sockets, `reqwest`, …)
46//! can be `.await`ed directly in UI code.
47
48mod blocking;
49mod executor;
50mod ext;
51mod install;
52
53pub use blocking::{BlockingError, spawn_blocking};
54pub use executor::{AsyncRuntimeHandle, TaskHandle};
55pub use ext::EventContextAsyncExt;
56pub use install::TeksiloAppBuilderAsyncExt;