Tap client RPC acquisition causes

This commit is contained in:
elpresidank 2026-06-02 04:45:44 -05:00
parent f7f29c4df9
commit 461b04d064
2 changed files with 40 additions and 20 deletions

View file

@ -12,8 +12,8 @@ Verified source roots:
- Effect v4 subtree: `/home/elpresidank/YeeBois/projects/beep-effect2/.repos/effect-v4`
- Installed Effect beta used by this workspace: `ts/node_modules/effect`
Current signal counts from `ts/packages` after the 2026-06-02 request-response
queue stream slice:
Current signal counts from `ts/packages` after the 2026-06-02 client RPC
acquisition cause tap slice:
| Signal | Count |
| --- | ---: |
@ -138,6 +138,10 @@ Notes:
around the socket program by sandboxing the Effect and handling the resulting
`Cause` in the Effect pipeline before the Fastify fire-and-forget
`runPromise` boundary.
- The client RPC acquisition cause tap slice removed the Promise `.catch` used
only to update connection state on runtime/client acquisition failure.
`effect-rpc-client.ts` now uses `Effect.tapCause` and `Cause.pretty` before
the public Promise boundary.
- `Record<string, any>` and `throwLibrarianServiceError` are now clean in
`ts/packages`.
@ -985,6 +989,27 @@ Notes:
- `cd ts && bun run test`
- `git diff --check`
### 2026-06-02: Client RPC Acquisition Cause Tap Slice
- Status: migrated and root-verified.
- Completed:
- `ts/packages/client/src/socket/effect-rpc-client.ts` now observes
runtime/client acquisition failures with `Effect.tapCause` and
`Cause.pretty`.
- Removed the Promise `.catch(...)` that only updated local connection state
after `runtime.runPromise(TrustGraphRpcClientService)`.
- Removed the local `errorMessage` helper and its message-field assertion.
- Public `dispatch`, `dispatchStream`, and `close` Promise facades remain
compatibility boundaries.
- Verification:
- `cd ts && bun run check:tsgo`
- `bun run --cwd ts/packages/client build`
- `bun run --cwd ts/packages/client test`
- `cd ts && bun run check`
- `cd ts && bun run build`
- `cd ts && bun run test`
- `git diff --check`
## Subagent Findings To Preserve
- MCP/workbench:

View file

@ -1,4 +1,4 @@
import { Context, Effect, Layer, ManagedRuntime, Stream } from "effect";
import { Cause, Context, Effect, Layer, ManagedRuntime, Stream } from "effect";
import type * as RpcGroup from "effect/unstable/rpc/RpcGroup";
import * as RpcClient from "effect/unstable/rpc/RpcClient";
import type { RpcClientError } from "effect/unstable/rpc/RpcClientError";
@ -128,13 +128,18 @@ export function makeEffectRpcClient(
};
const runtime = ManagedRuntime.make(makeClientLayer());
const clientPromise = runtime.runPromise(TrustGraphRpcClientService);
clientPromise.catch((cause) => {
setState({
status: "failed",
lastError: errorMessage(cause),
});
});
const clientPromise = runtime.runPromise(
TrustGraphRpcClientService.pipe(
Effect.tapCause((cause) =>
Effect.sync(() => {
setState({
status: "failed",
lastError: Cause.pretty(cause),
});
})
),
),
);
return {
subscribe: (listener) => {
@ -200,16 +205,6 @@ export function withDispatchRequestPolicy<A, E, R>(
return retryTimes > 0 ? timed.pipe(Effect.retry({ times: retryTimes })) : timed;
}
function errorMessage(cause: unknown): string {
if (cause instanceof Error) return cause.message;
if (typeof cause === "string") return cause;
if (cause !== null && typeof cause === "object" && "message" in cause) {
const message = (cause as { message?: unknown }).message;
if (typeof message === "string") return message;
}
return String(cause);
}
function normalizeTimeoutMs(timeoutMs: number | undefined): number {
if (timeoutMs === undefined || !Number.isFinite(timeoutMs) || timeoutMs <= 0) {
return DEFAULT_REQUEST_TIMEOUT_MS;