Skip to content

feat(clickhouse): accept any PSR-18 client in adapter constructor#13

Merged
loks0n merged 1 commit into
mainfrom
feat/accept-psr18-client
Jun 23, 2026
Merged

feat(clickhouse): accept any PSR-18 client in adapter constructor#13
loks0n merged 1 commit into
mainfrom
feat/accept-psr18-client

Conversation

@loks0n

@loks0n loks0n commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

What

Widens the ClickHouse adapter's $client constructor parameter (and the backing property) from the concrete Utopia\Client to the PSR-18 Psr\Http\Client\ClientInterface.

-        ?Client $client = null
+        ?ClientInterface $client = null

Why

The adapter only ever calls sendRequest() on the injected transport, so requiring the concrete Utopia\Client was stricter than necessary — and it blocked a real use case.

In a Swoole-coroutine server, the default transport (a cURL client with withConnectionReuse()) keeps a single CurlHandle on the instance. When the adapter is shared as a singleton across concurrent coroutines, that one handle gets clobbered by concurrent requests — it is not coroutine-safe.

The fix for that is Utopia\Client\Pool, which borrows a client from a bounded pool per request and reclaims it. But Pool implements ClientInterface/StreamingClientInterface — it is not a Utopia\Client — so it could not be passed in. Widening to ClientInterface unblocks it:

$transport = new Pool($connections); // Utopia\Client\Pool
$adapter = new ClickHouse($host, $user, $pass, $port, $secure, client: $transport);

The default still constructs the same cURL-backed Utopia\Client, so existing callers are unaffected.

Notes

  • Added psr/http-client as an explicit dependency (previously only transitive via utopia-php/client), since the source now references it directly.
  • composer check (PHPStan max) and pint pass; unit tests green.

🤖 Generated with Claude Code

Widen the ClickHouse adapter's $client parameter from the concrete
Utopia\Client to the PSR-18 ClientInterface. The adapter only ever calls
sendRequest() on the transport, so the narrower type was unnecessary and
blocked passing a Utopia\Client\Pool — which is a ClientInterface but not
a Utopia\Client — to share a bounded set of connections across concurrent
coroutine callers (the default single-handle cURL client is not
coroutine-safe when the adapter is shared).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@loks0n loks0n merged commit dd77631 into main Jun 23, 2026
4 checks passed
@greptile-apps

greptile-apps Bot commented Jun 23, 2026

Copy link
Copy Markdown

Greptile Summary

This PR widens the ClickHouse adapter transport type to accept any PSR-18 client. The main changes are:

  • Adds psr/http-client as a direct dependency.
  • Changes the injected ClickHouse client type from Utopia\Client to ClientInterface.
  • Keeps the existing default cURL-backed Utopia\Client transport.

Confidence Score: 5/5

The change is narrowly scoped and merge-safe.

The adapter continues to use only the PSR-18 sendRequest contract, while the default transport behavior remains unchanged for existing callers.

T-Rex T-Rex Logs

What T-Rex did

  • The base run rejected the non-Utopia PSR-18 client with TypeError and EXIT_CODE: 1.
  • The head run accepted the same client, returning constructor_result=success, adapter_class=Utopia\Usage\Adapter\ClickHouse, and EXIT_CODE: 0.
  • Two log artifacts were captured to document the base and head run outcomes.

View all artifacts

T-Rex Ran code and verified through T-Rex

Reviews (1): Last reviewed commit: "feat(clickhouse): accept any PSR-18 clie..." | Re-trigger Greptile

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