From 4a2f024846ca1b0bbdb4f6904bae964756c9f701 Mon Sep 17 00:00:00 2001 From: nsfisis Date: Mon, 31 Aug 2026 00:22:02 +0900 Subject: feat(plugin): serve HttpDownloader's async surface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit add() and addCopy() answer with a promise, and enableAsync(), wait() and countActiveJobs() answer alongside them. The Rust future runs to completion before the promise is handed over, so requests a plugin starts together run one after another rather than overlapping; overlapping them needs a promise representation that crosses the boundary unresolved. Everything else the surface does is preserved. add() still refuses a downloader outside a Loop, and it does so by throwing out of the call the way PHP does, where a failed request instead arrives as a rejection the caller handles — __shirabe_rejected_promise is the failure half of the resolved- promise helper. wait() and countActiveJobs() answer for a downloader with no outstanding job, which, once every request settles before its call returns, it never has. This is where HttpDownloader parts company with ProcessExecutor, whose async surface stays an explicit error: executeAsync() resolves its promise with a Symfony Process, whose state is the proc_open() resource of whichever process called start(), where a request resolves its promise with a Response. Co-Authored-By: Claude Opus 5 (1M context) --- docs/dev/php-rpc.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'docs/dev/php-rpc.md') diff --git a/docs/dev/php-rpc.md b/docs/dev/php-rpc.md index 6aa1d737..d2ce4ae5 100644 --- a/docs/dev/php-rpc.md +++ b/docs/dev/php-rpc.md @@ -167,9 +167,12 @@ Notable internal helpers: `selfDir`/`installedIsLocalDir` restore) into the worker; skipped only when the class is not even autoloadable there, i.e. no Composer PHP runtime and therefore no observer code. - `__shirabe_resolved_promise` — wraps a value in `\React\Promise\resolve()`, so a Rust method - whose PHP signature declares `PromiseInterface` (the `DownloadManager` surface) can answer - with the object type the caller expects. The Rust future has already run to completion by - then; deferred resolution across the boundary does not exist yet. + whose PHP signature declares `PromiseInterface` (the `DownloadManager` and `HttpDownloader` + surfaces) can answer with the object type the caller expects. The Rust future has already run + to completion by then; deferred resolution across the boundary does not exist yet. +- `__shirabe_rejected_promise` — the failure half of the same: `\React\Promise\reject()` over + the exception a `Throw` frame's four fields describe, so a failed request reaches the caller + as a rejection it handles rather than as a throw out of the call that started it. - `__shirabe_settle_promise` — the inverse: drains a promise a plugin returned to Rust. React settles synchronously, so an already-settled promise yields its value here (a rejection is re-thrown as the Throw reply); one that is still pending is an explicit error. -- cgit v1.3.1-4-g156e