Forwarder: resolve opencode workspace/session dynamically per request (#28)
CI / build + unit (push) Successful in 32s
CI / build + unit (push) Successful in 32s
This commit was merged in pull request #28.
This commit is contained in:
@@ -824,6 +824,37 @@ describe('MeshService notify webhook', () => {
|
||||
}
|
||||
});
|
||||
|
||||
it('retries a webhook POST that answers with an HTTP error status and stops on success', async () => {
|
||||
process.env.MESH_NOTIFY_URL = 'http://notify.example/hook';
|
||||
process.env.MESH_NOTIFY_CHANNEL = '0';
|
||||
const fetchMock = vi
|
||||
.fn()
|
||||
.mockResolvedValueOnce({ ok: false, status: 502 })
|
||||
.mockResolvedValueOnce({ ok: false, status: 502 })
|
||||
.mockResolvedValueOnce({ ok: true, status: 200 });
|
||||
vi.stubGlobal('fetch', fetchMock);
|
||||
const warnSpy = vi.spyOn(Logger.prototype, 'warn');
|
||||
const sleep = vi.fn(async (_ms: number) => {});
|
||||
const svc = new MeshService();
|
||||
(svc as unknown as { sleep(ms: number): Promise<void> }).sleep = sleep;
|
||||
try {
|
||||
expect(() => svc.injectMessage('hi', 42)).not.toThrow();
|
||||
|
||||
await waitFor(() => fetchMock.mock.calls.length === 3);
|
||||
// HTTP 502 twice, then 200: exactly 3 POSTs, no dropped log
|
||||
expect(fetchMock).toHaveBeenCalledTimes(3);
|
||||
const warns = warnSpy.mock.calls.map((c) => String(c[0]));
|
||||
expect(warns.some((w) => w.includes('attempt 1/4'))).toBe(true);
|
||||
expect(warns.some((w) => w.includes('HTTP 502'))).toBe(true);
|
||||
expect(warns.some((w) => w.includes('notify dropped'))).toBe(false);
|
||||
} finally {
|
||||
warnSpy.mockRestore();
|
||||
vi.unstubAllGlobals();
|
||||
delete process.env.MESH_NOTIFY_URL;
|
||||
delete process.env.MESH_NOTIFY_CHANNEL;
|
||||
}
|
||||
});
|
||||
|
||||
it('gives up after 4 attempts and logs notify dropped', async () => {
|
||||
process.env.MESH_NOTIFY_URL = 'http://notify.example/hook';
|
||||
process.env.MESH_NOTIFY_CHANNEL = '0';
|
||||
|
||||
@@ -452,11 +452,12 @@ export class MeshService implements OnModuleInit, OnModuleDestroy {
|
||||
const maxAttempts = NOTIFY_RETRY_DELAYS_MS.length + 1;
|
||||
for (let attempt = 1; ; attempt++) {
|
||||
try {
|
||||
await fetch(this.notifyUrl, {
|
||||
const res = await fetch(this.notifyUrl, {
|
||||
method: 'POST',
|
||||
headers: { 'content-type': 'application/json' },
|
||||
body: JSON.stringify(body),
|
||||
});
|
||||
if (res && !res.ok) throw new Error('HTTP ' + res.status); // HTTP errors retry like network failures
|
||||
return; // success on any attempt — same as today's single POST
|
||||
} catch (err: unknown) {
|
||||
const msg = (err as Error).message;
|
||||
|
||||
Reference in New Issue
Block a user