2026-06-01 20:26:47 -05:00
|
|
|
import { Effect } from "effect";
|
2026-06-01 17:23:34 -05:00
|
|
|
import { describe, expect, it, vi } from "vitest";
|
2026-06-01 20:26:47 -05:00
|
|
|
import { DispatchError } from "../rpc/contract";
|
|
|
|
|
import { type DispatchInput, withDispatchRequestPolicy } from "../socket/effect-rpc-client";
|
|
|
|
|
import { makeBaseApiWithRpc } from "../socket/trustgraph-socket";
|
2026-06-01 17:23:34 -05:00
|
|
|
|
|
|
|
|
const input: DispatchInput = {
|
|
|
|
|
scope: "global",
|
|
|
|
|
service: "config",
|
|
|
|
|
request: { operation: "list" },
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
describe("Effect RPC request policy", () => {
|
|
|
|
|
it("threads BaseApi timeout and retry options into dispatch calls", async () => {
|
|
|
|
|
const dispatch = vi.fn(() => Promise.resolve({ ok: true }));
|
2026-06-01 20:26:47 -05:00
|
|
|
const api = makeBaseApiWithRpc("alice", undefined, "ws://example.test/rpc", {
|
2026-06-01 17:23:34 -05:00
|
|
|
dispatch,
|
2026-06-01 20:26:47 -05:00
|
|
|
dispatchStream: vi.fn(() => Promise.resolve(undefined)),
|
|
|
|
|
close: vi.fn(() => Promise.resolve()),
|
|
|
|
|
subscribe: vi.fn(() => () => {}),
|
|
|
|
|
});
|
2026-06-01 17:23:34 -05:00
|
|
|
|
|
|
|
|
await api.makeRequest("config", { operation: "list" }, 25, 2);
|
|
|
|
|
|
|
|
|
|
expect(dispatch).toHaveBeenCalledWith(input, {
|
|
|
|
|
timeoutMs: 25,
|
|
|
|
|
retries: 2,
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("rejects stalled dispatch calls at the requested timeout", async () => {
|
|
|
|
|
const startedAt = Date.now();
|
|
|
|
|
|
|
|
|
|
await expect(
|
2026-06-01 20:26:47 -05:00
|
|
|
Effect.runPromise(withDispatchRequestPolicy(Effect.never, { timeoutMs: 20, retries: 1 })),
|
2026-06-01 17:23:34 -05:00
|
|
|
).rejects.toBeInstanceOf(DispatchError);
|
|
|
|
|
|
|
|
|
|
expect(Date.now() - startedAt).toBeLessThan(1_000);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("retries dispatch failures up to the requested attempt count", async () => {
|
|
|
|
|
let attempts = 0;
|
|
|
|
|
|
2026-06-01 20:26:47 -05:00
|
|
|
await expect(
|
|
|
|
|
Effect.runPromise(
|
|
|
|
|
withDispatchRequestPolicy(
|
|
|
|
|
Effect.suspend(() => {
|
|
|
|
|
attempts += 1;
|
|
|
|
|
if (attempts < 3) {
|
|
|
|
|
return Effect.fail(new DispatchError({ message: String(attempts) }));
|
|
|
|
|
}
|
|
|
|
|
return Effect.succeed({ ok: true });
|
|
|
|
|
}),
|
|
|
|
|
{ timeoutMs: 100, retries: 3 },
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
).resolves.toEqual({ ok: true });
|
2026-06-01 17:23:34 -05:00
|
|
|
|
|
|
|
|
expect(attempts).toBe(3);
|
|
|
|
|
});
|
|
|
|
|
});
|