aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe/src/util/sync_executor.rs
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-07-17 16:37:58 +0900
committernsfisis <nsfisis@gmail.com>2026-07-17 16:37:58 +0900
commitc5c527d87425ff93a4f983d36e12bd1c4b565e52 (patch)
tree47696883b4f7bf132f6dc6ebc1db777ab57addbc /crates/shirabe/src/util/sync_executor.rs
parent2dc55eec52ee2c6993e64d8bb11c96a4f2ec5c6d (diff)
downloadphp-shirabe-c5c527d87425ff93a4f983d36e12bd1c4b565e52.tar.gz
php-shirabe-c5c527d87425ff93a4f983d36e12bd1c4b565e52.tar.zst
php-shirabe-c5c527d87425ff93a4f983d36e12bd1c4b565e52.zip
refactor(curl-downloader): rewrite as a single async fn, drop Job/tick
Replaces the Job-table + tick()-driven polling loop with one async download() that sends, decides (retry/redirect/fail/succeed via a new decide() extracted from the former run_job), and loops until it resolves — no more resolve/reject callbacks. The client switches from reqwest::blocking::Client to the non-blocking reqwest::Client, with body streaming now via tokio::fs. Because real async I/O needs a live tokio reactor and none runs yet at the process level (sync_executor::block_on is a no-reactor busy-spin executor that only works when awaited futures resolve synchronously), HttpDownloader::start_job drives CurlDownloader::download() through a dedicated temporary current_thread Runtime (curl_runtime(), marked TODO(phase-e)) instead. This keeps concurrency characteristics unchanged for now — start_job still resolves one job at a time — real parallel I/O lands once HttpDownloader/Loop are rearchitected on top of FuturesUnordered. count_active_jobs' curl.tick() polling and the Job.settled/curl_id plumbing are removed as dead weight now that start_job settles curl jobs synchronously, same as the rfs path already did. abort_request is dropped: it had no caller (the PHP Promise-cancellation flow it backs was never ported), and the job table it operated on no longer exists. Verified manually against real network I/O (sandbox disabled): `shirabe show -a` (JSON metadata, in-memory body) and `shirabe create-project` (actual dist zip download + extraction) both complete correctly with no hang. Two unrelated pre-existing bugs surfaced during manual testing (an event-dispatcher subscriber wiring gap during `require`, and a RefCell reentrancy panic in `diagnose`) reproduce identically on the pre-change code and are out of scope here.
Diffstat (limited to 'crates/shirabe/src/util/sync_executor.rs')
-rw-r--r--crates/shirabe/src/util/sync_executor.rs14
1 files changed, 10 insertions, 4 deletions
diff --git a/crates/shirabe/src/util/sync_executor.rs b/crates/shirabe/src/util/sync_executor.rs
index b7512c2d..ee0995fc 100644
--- a/crates/shirabe/src/util/sync_executor.rs
+++ b/crates/shirabe/src/util/sync_executor.rs
@@ -1,10 +1,16 @@
//! Minimal synchronous future executor used as a drop-in for the `tokio::runtime::Runtime::new()`
//! + `block_on` sync bridges scattered across the codebase (repository / installer / downloader).
//!
-//! Those bridges drive `async fn`s whose `.await` points all resolve synchronously: the only async
-//! I/O (reqwest in `CurlDownloader`) is performed through a blocking client, so no reactor is
-//! required. Nesting `tokio` runtimes is forbidden ("Cannot start a runtime from within a runtime"),
-//! which is why this no-reactor executor exists; it can be nested freely.
+//! Those bridges drive `async fn`s whose `.await` points all resolve synchronously — this relies
+//! on the invariant below. `CurlDownloader` no longer qualifies: it now performs real async I/O
+//! via a non-blocking `reqwest::Client`, so `HttpDownloader` drives it through its own dedicated
+//! `tokio::runtime::Runtime` instead (see `http_downloader::curl_runtime`), not through this
+//! module. The other call sites (`file_downloader.rs`, `version_guesser.rs`,
+//! `installation_manager.rs`, `composer_repository.rs`, `sync_helper.rs`) still rely on this
+//! module because none of their awaited futures actually park on a reactor.
+//!
+//! Nesting `tokio` runtimes is forbidden ("Cannot start a runtime from within a runtime"), which is
+//! why this no-reactor executor exists for those remaining call sites; it can be nested freely.
//!
//! TODO(phase-e): remove this module once the async bridges are either made genuinely synchronous or
//! consolidated onto a single shared runtime driven from `main`.