diff options
Diffstat (limited to 'docs/dev')
| -rw-r--r-- | docs/dev/php-rpc.md | 9 | ||||
| -rw-r--r-- | docs/dev/plugin-class-classification.md | 20 |
2 files changed, 22 insertions, 7 deletions
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. diff --git a/docs/dev/plugin-class-classification.md b/docs/dev/plugin-class-classification.md index a383f7c6..5cb8fd6e 100644 --- a/docs/dev/plugin-class-classification.md +++ b/docs/dev/plugin-class-classification.md @@ -415,10 +415,22 @@ its options, its TLS defaults and the authentication it collects into the run's IO are state the two worlds have to share, and a plugin-`new`ed one allocates a Rust-side entity rather than a second downloader the graph knows nothing about. `get()` and `copy()` answer with a -`Composer\Util\Http\Response` the child holds as a value (see below); the -async surface — `add()`, `addCopy()`, `wait()`, `enableAsync()`, -`countActiveJobs()` — is still an explicit error, because driving it needs a -promise representation that crosses the boundary unresolved. +`Composer\Util\Http\Response` the child holds as a value (see below), and the +async surface answers too, with the future driven to completion before the +promise is handed over. Requests a plugin starts together therefore run one +after another rather than overlapping; overlapping them needs a promise +representation that crosses the boundary unresolved. Everything else the async +surface does is preserved: `add()` still refuses a downloader outside a `Loop`, +a failed request still arrives as a rejection rather than as a throw, and +`wait()` and `countActiveJobs()` still answer for a downloader that holds no +outstanding job — which, once every request settles before its call returns, it +never does. + +This is where `ProcessExecutor` and `HttpDownloader` part company. The +executor's async surface stays an explicit error because `executeAsync()` +resolves its promise with a `Symfony\Component\Process\Process`, whose state +is the `proc_open()` resource of whichever process called `start()`; a request +resolves its promise with a `Response`, which is data. `Loop` remains guarded, so `Composer::getLoop()` is still an explicit error and neither the graph's own executor nor its downloader is reachable through |
