diff --git a/libs/services/src/lib/server-storage/server-api-client.spec.ts b/libs/services/src/lib/server-storage/server-api-client.spec.ts index fceb84af6..241437275 100644 --- a/libs/services/src/lib/server-storage/server-api-client.spec.ts +++ b/libs/services/src/lib/server-storage/server-api-client.spec.ts @@ -110,6 +110,23 @@ describe('ServerApiClient', () => { expect(status.reportOffline).toHaveBeenCalledTimes(1); }); + it('reports a keepalive answer cut off after its headers as offline', async () => { + const cutOff = jest.fn().mockResolvedValue({ + ...response(200), + json: async () => { + throw new TypeError('body cut off'); + }, + }); + + // Saved, on a version it cannot tell (see the write queue). + await expect( + client(cutOff).sendKeepalive('PUT', '/user-state/a/b', { + value: 1, + }) + ).resolves.toEqual({ status: 'saved', tag: undefined }); + expect(status.reportOffline).toHaveBeenCalled(); + }); + it('reports a gateway answering for a down backend on a keepalive write', async () => { const down = jest.fn().mockResolvedValue(response(502)); diff --git a/libs/services/src/lib/server-storage/server-api-client.ts b/libs/services/src/lib/server-storage/server-api-client.ts index 3b309380b..7261f59e1 100644 --- a/libs/services/src/lib/server-storage/server-api-client.ts +++ b/libs/services/src/lib/server-storage/server-api-client.ts @@ -201,11 +201,12 @@ export class ServerApiClient { signal: this.timeoutSignal(), }); if (response.ok) { - const body = (await response - .json() - .catch( - () => ({}) - )) as Partial; + const body = (await response.json().catch(() => { + // Saved, on a version it cannot tell: cut off after its + // headers, which counts as offline, as for requests. + this.options.status.reportOffline(); + return {}; + })) as Partial; return { status: 'saved', tag: body?.tag }; } if (GATEWAY_UNAVAILABLE.has(response.status)) {