UNPKG

convex

Version:

Client for the Convex Cloud

162 lines (141 loc) 4.46 kB
import { test, expect, beforeEach } from "@jest/globals"; import { RequestManager } from "./request_manager"; import { Long } from "../long.js"; import { MutationRequest } from "./protocol.js"; let requestManager: RequestManager; beforeEach(() => { requestManager = new RequestManager(); }); test("hasIncompleteRequests", () => { // Starts false. expect(requestManager.hasIncompleteRequests()).toBe(false); // When we request a mutation it becomes true. let message: MutationRequest = { type: "Mutation", requestId: 0, udfPath: "myMutation", args: [], }; let _ = requestManager.request(message); expect(requestManager.hasIncompleteRequests()).toBe(true); // Request a second mutation and receive the first's response. // Should still have an outstanding mutation. message = { type: "Mutation", requestId: 1, udfPath: "myMutation", args: [], }; _ = requestManager.request(message); requestManager.onResponse({ type: "MutationResponse", requestId: 0, success: true, result: null, ts: Long.fromNumber(0), logLines: [], }); expect(requestManager.hasIncompleteRequests()).toBe(true); // When the second response comes back we no longer have any outstanding mutations. requestManager.onResponse({ type: "MutationResponse", requestId: 1, success: true, result: null, ts: Long.fromNumber(0), logLines: [], }); expect(requestManager.hasIncompleteRequests()).toBe(false); }); /** * A test that simulates a WebSocket disconnection half-way through the mutation * flow. */ test("mutation retries", async () => { // Request a mutation. const message: MutationRequest = { type: "Mutation", requestId: 0, udfPath: "myMutation", args: [], }; const mutationRequest = requestManager.request(message); // Receive the response. requestManager.onResponse({ type: "MutationResponse", requestId: 0, success: true, result: null, ts: Long.fromNumber(0), logLines: [], }); // Pretend that we become disconnected and reconnect. // We should request the mutation because we haven't transitioned past the // timestamp the mutation was committed at yet. expect(requestManager.restart()).toEqual([message]); // Receive another response (because we restarted and requested it again) requestManager.onResponse({ type: "MutationResponse", requestId: 0, success: true, result: null, ts: Long.fromNumber(0), logLines: [], }); // Transition to ts=1 requestManager.removeCompleted(Long.fromNumber(1)); // Return the result of the mutation now that we've transitioned past the // mutation timestamp. const result = await mutationRequest; expect(result).toBe(null); // The if we restart now, the mutation should no longer be re-requested. expect(requestManager.restart()).toEqual([]); }); /** * Another disconnection test * * This time upon reconnect we transition past the mutation immediately when we * reconnect (before getting the second response). */ test("mutation retries with transition", async () => { // Request a mutation. const message: MutationRequest = { type: "Mutation", requestId: 0, udfPath: "myMutation", args: [], }; const mutationRequest = requestManager.request(message); // Receive the response. requestManager.onResponse({ type: "MutationResponse", requestId: 0, success: true, result: null, ts: Long.fromNumber(0), logLines: [], }); // Pretend that we become disconnected and reconnect. // We should request the mutation because we haven't transitioned past the // timestamp the mutation was committed at yet. expect(requestManager.restart()).toEqual([message]); // Transition to ts=1 requestManager.removeCompleted(Long.fromNumber(1)); // Return the result of the mutation now that we've transitioned past the // mutation timestamp. const result = await mutationRequest; expect(result).toBe(null); // The if we restart now, the mutation should no longer be re-requested because // we've already observed it. expect(requestManager.restart()).toEqual([]); // Receive another response (because we requested it again). // This response just needs to not crash the client. requestManager.onResponse({ type: "MutationResponse", requestId: 0, success: true, result: null, ts: Long.fromNumber(0), logLines: [], }); });