refactor: 리펙토링
This commit is contained in:
@@ -380,6 +380,48 @@ describe("IndexedDB runtime", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("shares one native open request across concurrent callers", async () => {
|
||||
const memory = new MemoryIndexedDbFactory();
|
||||
const nativeOpen = vi.spyOn(memory.factory, "open");
|
||||
const runtime = createIndexedDbRuntime(dependencies(memory));
|
||||
|
||||
const results = await Promise.all([
|
||||
runtime.open(),
|
||||
runtime.open(),
|
||||
runtime.open(),
|
||||
]);
|
||||
|
||||
expect(nativeOpen).toHaveBeenCalledOnce();
|
||||
expect(results).toEqual([
|
||||
{ ok: true, value: undefined },
|
||||
{ ok: true, value: undefined },
|
||||
{ ok: true, value: undefined },
|
||||
]);
|
||||
});
|
||||
|
||||
it("isolates a caller abort from the shared native open request", async () => {
|
||||
const memory = new MemoryIndexedDbFactory();
|
||||
memory.blockNextOpen();
|
||||
const nativeOpen = vi.spyOn(memory.factory, "open");
|
||||
const runtime = createIndexedDbRuntime(dependencies(memory));
|
||||
const cancelledCaller = new AbortController();
|
||||
|
||||
const surviving = runtime.open();
|
||||
const cancelled = runtime.open(cancelledCaller.signal);
|
||||
await Promise.resolve();
|
||||
cancelledCaller.abort();
|
||||
|
||||
expect(await cancelled).toMatchObject({
|
||||
ok: false,
|
||||
error: { code: "ABORTED", operation: "INDEXEDDB_OPEN" },
|
||||
});
|
||||
expect(nativeOpen).toHaveBeenCalledOnce();
|
||||
|
||||
memory.releaseBlockedOpen();
|
||||
expect(await surviving).toEqual({ ok: true, value: undefined });
|
||||
expect(runtime.getStatus()).toEqual({ kind: "READY", schemaVersion: 1 });
|
||||
});
|
||||
|
||||
it("times out a blocked upgrade, then closes a late successful connection", async () => {
|
||||
const memory = new MemoryIndexedDbFactory();
|
||||
memory.blockNextOpen();
|
||||
@@ -422,6 +464,50 @@ describe("IndexedDB runtime", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("retains native open ownership after a blocked timeout until late success", async () => {
|
||||
const memory = new MemoryIndexedDbFactory();
|
||||
memory.blockNextOpen();
|
||||
const nativeOpen = vi.spyOn(memory.factory, "open");
|
||||
let timeout: (() => void) | undefined;
|
||||
const runtime = createIndexedDbRuntime(
|
||||
dependencies(memory, {
|
||||
blockedTimeoutMs: 25,
|
||||
scheduler: {
|
||||
setTimeout: (callback) => {
|
||||
timeout = callback;
|
||||
return "blocked-timer";
|
||||
},
|
||||
clearTimeout: () => undefined,
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
const first = runtime.open();
|
||||
await Promise.resolve();
|
||||
timeout?.();
|
||||
await expect(first).resolves.toMatchObject({
|
||||
ok: false,
|
||||
error: { code: "BLOCKED" },
|
||||
});
|
||||
|
||||
const second = runtime.open();
|
||||
await Promise.resolve();
|
||||
const nativeOpenCountBeforeLateSuccess = nativeOpen.mock.calls.length;
|
||||
memory.releaseBlockedOpen();
|
||||
|
||||
await expect(second).resolves.toMatchObject({
|
||||
ok: false,
|
||||
error: { code: "BLOCKED" },
|
||||
});
|
||||
await Promise.resolve();
|
||||
expect(nativeOpenCountBeforeLateSuccess).toBe(1);
|
||||
expect(memory.isConnectionClosed()).toBe(true);
|
||||
expect(runtime.getStatus()).toEqual({
|
||||
kind: "CLOSED",
|
||||
reason: "NOT_OPENED",
|
||||
});
|
||||
});
|
||||
|
||||
it("closes immediately on versionchange and isolates listener failures", async () => {
|
||||
const memory = new MemoryIndexedDbFactory();
|
||||
const onVersionChange = vi.fn(() => {
|
||||
|
||||
Reference in New Issue
Block a user