Skip to content

chore: migrate bare curl/utopia-fetch to utopia-php/client#237

Open
loks0n wants to merge 5 commits into
mainfrom
chore/migrate-utopia-client
Open

chore: migrate bare curl/utopia-fetch to utopia-php/client#237
loks0n wants to merge 5 commits into
mainfrom
chore/migrate-utopia-client

Conversation

@loks0n

@loks0n loks0n commented Jun 22, 2026

Copy link
Copy Markdown
Member

What

Migrates all bare cURL and utopia-php/fetch calls onto utopia-php/client, coupling directly to its PSR-18 exception types for control flow (no translation layer).

Net −69 LoC across the source (excluding the generated lockfile).

Changes

src/Executor/Runner/Docker.php — the three bare-cURL closures (sendCreateRuntimeRequest, executeV2, executeV5) now use the Curl adapter + RequestFactory:

  • Retry loop catches the client's exceptions directly: ConnectionException/DnsException → retry, TimeoutExceptionEXECUTION_TIMEOUT for v2 (else internal error).
  • Faithful to prior wire behavior: multi-value response headers (Set-Cookie), v2 JSON_FORCE_OBJECT, the implicit application/x-www-form-urlencoded content type cURL adds for a raw v5 body, and CURLOPT_NOBODY for HEAD.
  • The Curl adapter is required here (not SwooleCoroutine): Swoole's coroutine HTTP client collapses duplicate response headers, which would break the multi-cookie behavior.

tests/e2e/Client.php — off utopia-php/fetch, selecting the adapter by context (Curl outside a coroutine, SwooleCoroutine inside) so the 60+ direct calls and the concurrent log-streaming test both work without a bootstrap hook.

Build / deps / CI

  • composer.json: php >=8.4, platform 8.4, +utopia-php/client, −utopia-php/fetch (lock regenerated). utopia-php/client requires PHP 8.4 — its source uses 8.4-only new Foo()->bar() syntax.
  • Dockerfile: build on phpswoole/swoole:6.2.1-php8.4-alpine (openruntimes/base has no PHP 8.4 build). Adds docker-cli (the executor shells out to Docker) and sets WORKDIR /usr/local/.
  • ci.yml: unit/e2e Swoole test images 5.1.2-php8.36.2.1-php8.4.
  • Incidental rector php84 idioms (array_any, new-without-parens) applied — required for refactor:check to stay green on the 8.4 platform.

Verification

  • composer analyze (phpstan lvl 8) ✅ · format:check (pint) ✅ · refactor:check (rector) ✅
  • Unit tests ✅ 7/7 under PHP 8.4 + Swoole 6.2.1
  • docker build ✅ — image boots clean (PHP 8.4.21, app/http.php parses, docker CLI present, all three utopia/client adapters autoload)

Note: this also moves production Swoole 5.1.2 → 6.2.1. Full coroutine-server behavior under load is exercised by the e2e job, which can now build and run.

🤖 Generated with Claude Code

loks0n and others added 2 commits June 22, 2026 16:05
Replace the three bare-cURL closures in Docker.php and the utopia-php/fetch
e2e test client with utopia-php/client, coupling directly to its PSR-18
exception types for retry/timeout control flow.

- Docker.php: Curl adapter + RequestFactory; retry loop catches
  ConnectionException/DnsException (retry) and TimeoutException (v2
  EXECUTION_TIMEOUT). Preserves multi-value response headers, v2
  JSON_FORCE_OBJECT, and v5's implicit form-urlencoded content type.
- tests/e2e/Client.php: utopia-php/client with context-based adapter
  (Curl outside a coroutine, SwooleCoroutine inside) so direct calls and
  the concurrent streaming test both work.
- composer: php >=8.4, platform 8.4, +utopia-php/client, -utopia-php/fetch.
- Build on phpswoole/swoole:6.2.1-php8.4-alpine (openruntimes/base has no
  8.4 build); add docker-cli, set WORKDIR. CI test images -> php8.4.
- Apply rector php84 idioms required by the platform bump.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…client

# Conflicts:
#	.github/workflows/ci.yml
#	Dockerfile
#	app/controllers.php
#	composer.json
#	composer.lock
#	src/Executor/Runner/Docker.php
@greptile-apps

greptile-apps Bot commented Jun 22, 2026

Copy link
Copy Markdown

Greptile Summary

This PR migrates all bare-cURL and utopia-php/fetch HTTP calls onto utopia-php/client, adopting its PSR-18 exception hierarchy directly for retry and timeout control flow. The net result is −69 LoC with no behavioural regressions across the three HTTP paths (sendCreateRuntimeRequest, executeV2, executeV5) and the e2e test client.

  • Docker.php: three bare-cURL closures replaced with HttpClient(new CurlAdapter()); errNo checks replaced by catching ConnectionException/DnsException (retry) and ClientTimeoutException/NetworkExceptionInterface (throw); status-code branching, multi-value Set-Cookie header normalisation, and JSON_FORCE_OBJECT encoding are all preserved.
  • tests/e2e/Client.php: standalone Client class using RequestFactory with adapter selected by coroutine context (SwooleAdapter inside, CurlAdapter outside); multipart, form-url-encoded, and JSON request paths explicitly handled.
  • Build/deps: PHP platform and Swoole bumped to 8.4/6.2.1; utopia-php/client 0.1.4 added as a production dependency, utopia-php/fetch removed.

Confidence Score: 5/5

Safe to merge; all three HTTP paths preserve their prior wire behaviour and error-handling contracts, and the e2e test client correctly selects the coroutine-aware adapter at runtime.

The migration is mechanically faithful: retry/timeout branching, status-code logic, header normalisation, and content-type fallbacks all match the old cURL code. The exception hierarchy maps cleanly to the prior errNo checks, and no path silently drops or transforms errors in a new way.

No files require special attention.

Important Files Changed

Filename Overview
src/Executor/Runner/Docker.php Replaces three bare-cURL closures with utopia-php/client's Curl adapter; retry/timeout logic, status-code branching, and header normalisation are all behaviourally equivalent to the old code.
tests/e2e/Client.php Migrates from FetchClient subclass to a standalone Client using RequestFactory; adapter selection (Curl vs SwooleCoroutine) based on coroutine context is correct; multipart/form-data and streaming paths are handled.
composer.json Adds utopia-php/client 0.1.* to production dependencies and removes utopia-php/fetch from dev; PHP platform bumped to 8.4.
composer.lock Lock regenerated; adds utopia-php/client 0.1.4 with its transitive deps (pools, span, telemetry); removes utopia-php/fetch; several other packages bumped as incidental dependency resolution.

Reviews (3): Last reviewed commit: "chore: bump utopia-php/client to 0.1.4, ..." | Re-trigger Greptile

Comment thread src/Executor/Runner/Docker.php
Comment thread tests/e2e/Client.php Outdated
loks0n and others added 3 commits June 22, 2026 16:35
The test client's body encoding fell through to JSON for any non-GET
request, so a caller-set content-type of multipart/form-data (used by
the binary-body execution scenarios) was sent as JSON under a multipart
header. Route multipart -> RequestFactory::multipart (stripping the
boundary-less content type so a boundary is emitted) and form-urlencoded
-> RequestFactory::form.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The create-runtime request was a closure invoked exactly once in the
loop directly below it; inline it (dropping the 10-var capture list,
call_user_func, and now-unused ResponseInterface import). executeV2/V5
stay closures since they are version-selected and share the retry loop.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
0.1.4 sets CURLOPT_NOBODY for HEAD requests inside the Curl adapter, so
executeV5 no longer needs to pass it explicitly.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant