mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-22 10:11:10 +00:00
* refactor(deadcode): trim auto-reply and CLI exports * refactor(deadcode): trim cron and task exports * refactor(deadcode): trim fleet and process exports * test(deadcode): exercise live task and process seams * test(fleet): cover stream redaction through owner module * refactor(security): trim dead internal exports * refactor(secrets): trim dead internal exports * refactor(deadcode): trim remaining src exports * refactor(deadcode): remove test-only runtime exports * refactor(deadcode): trim pairing test exports * refactor(deadcode): reconcile refreshed baseline * test(auto-reply): deduplicate queue state imports
173 lines
5.6 KiB
TypeScript
173 lines
5.6 KiB
TypeScript
/**
|
|
* Tests delivery queue runtime ordering and retry behavior.
|
|
*/
|
|
import { expectDefined } from "@openclaw/normalization-core";
|
|
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
|
import {
|
|
getActiveGatewayRootWorkCount,
|
|
resetGatewayWorkAdmission,
|
|
tryBeginGatewaySuspendAdmission,
|
|
} from "../process/gateway-work-admission.js";
|
|
import { runWithGatewayRootWorkAdmissionForTest } from "../process/gateway-work-admission.test-helpers.js";
|
|
|
|
const mocks = vi.hoisted(() => ({
|
|
coreDrainPendingDeliveries: vi.fn(async () => {}),
|
|
deliverOutboundPayloads: vi.fn(async () => []),
|
|
deliverRuntimeModuleLoads: 0,
|
|
}));
|
|
|
|
vi.mock("../infra/outbound/delivery-queue.js", () => ({
|
|
drainPendingDeliveries: mocks.coreDrainPendingDeliveries,
|
|
}));
|
|
|
|
vi.mock("../infra/outbound/deliver-runtime.js", () => {
|
|
mocks.deliverRuntimeModuleLoads += 1;
|
|
return {
|
|
deliverOutboundPayloads: mocks.deliverOutboundPayloads,
|
|
deliverOutboundPayloadsInternal: mocks.deliverOutboundPayloads,
|
|
};
|
|
});
|
|
|
|
type DeliveryQueueRuntimeModule = typeof import("./delivery-queue-runtime.js");
|
|
|
|
let drainPendingDeliveries: DeliveryQueueRuntimeModule["drainPendingDeliveries"];
|
|
|
|
const log = {
|
|
info: vi.fn(),
|
|
warn: vi.fn(),
|
|
error: vi.fn(),
|
|
};
|
|
|
|
beforeAll(async () => {
|
|
({ drainPendingDeliveries } = await import("./delivery-queue-runtime.js"));
|
|
});
|
|
|
|
beforeEach(() => {
|
|
resetGatewayWorkAdmission();
|
|
mocks.coreDrainPendingDeliveries.mockReset().mockResolvedValue(undefined);
|
|
mocks.deliverOutboundPayloads.mockReset().mockResolvedValue([]);
|
|
log.info.mockClear();
|
|
log.warn.mockClear();
|
|
log.error.mockClear();
|
|
});
|
|
|
|
afterEach(resetGatewayWorkAdmission);
|
|
|
|
describe("plugin-sdk delivery queue drainPendingDeliveries", () => {
|
|
it("defers lazy runtime resolution and core draining while suspension is prepared", async () => {
|
|
const suspension = tryBeginGatewaySuspendAdmission(() => {});
|
|
expect(suspension?.commit()).toBe(true);
|
|
|
|
const pending = drainPendingDeliveries({
|
|
drainKey: "demo:test",
|
|
logLabel: "Demo reconnect drain",
|
|
cfg: {},
|
|
log,
|
|
selectEntry: () => ({ match: false }),
|
|
});
|
|
await Promise.resolve();
|
|
|
|
expect(mocks.deliverRuntimeModuleLoads).toBe(0);
|
|
expect(mocks.coreDrainPendingDeliveries).not.toHaveBeenCalled();
|
|
|
|
expect(suspension?.release()).toBe(true);
|
|
await pending;
|
|
|
|
expect(mocks.deliverRuntimeModuleLoads).toBe(1);
|
|
expect(mocks.coreDrainPendingDeliveries).toHaveBeenCalledOnce();
|
|
expect(getActiveGatewayRootWorkCount()).toBe(0);
|
|
});
|
|
|
|
it("counts a reconnect drain independently from its admitted parent", async () => {
|
|
let finishDrain = () => {};
|
|
const drainStarted = new Promise<void>((resolveStarted) => {
|
|
mocks.coreDrainPendingDeliveries.mockImplementationOnce(
|
|
() =>
|
|
new Promise<void>((resolveDrain) => {
|
|
finishDrain = resolveDrain;
|
|
resolveStarted();
|
|
}),
|
|
);
|
|
});
|
|
const deliver = vi.fn(async () => []);
|
|
|
|
await runWithGatewayRootWorkAdmissionForTest(async () => {
|
|
expect(getActiveGatewayRootWorkCount()).toBe(1);
|
|
const pending = drainPendingDeliveries({
|
|
drainKey: "demo:test",
|
|
logLabel: "Demo reconnect drain",
|
|
cfg: {},
|
|
log,
|
|
deliver,
|
|
selectEntry: () => ({ match: false }),
|
|
});
|
|
await drainStarted;
|
|
|
|
expect(getActiveGatewayRootWorkCount()).toBe(2);
|
|
finishDrain();
|
|
await pending;
|
|
expect(getActiveGatewayRootWorkCount()).toBe(1);
|
|
});
|
|
|
|
expect(getActiveGatewayRootWorkCount()).toBe(0);
|
|
});
|
|
|
|
it("releases its independent root when the core drain rejects", async () => {
|
|
mocks.coreDrainPendingDeliveries.mockImplementationOnce(async () => {
|
|
expect(getActiveGatewayRootWorkCount()).toBe(1);
|
|
throw new Error("drain failed");
|
|
});
|
|
|
|
await expect(
|
|
drainPendingDeliveries({
|
|
drainKey: "demo:test",
|
|
logLabel: "Demo reconnect drain",
|
|
cfg: {},
|
|
log,
|
|
deliver: vi.fn(async () => []),
|
|
selectEntry: () => ({ match: false }),
|
|
}),
|
|
).rejects.toThrow("drain failed");
|
|
|
|
expect(getActiveGatewayRootWorkCount()).toBe(0);
|
|
});
|
|
|
|
it("injects the lazy outbound deliver runtime when no deliver fn is provided", async () => {
|
|
await drainPendingDeliveries({
|
|
drainKey: "demo:test",
|
|
logLabel: "Demo reconnect drain",
|
|
cfg: {},
|
|
log,
|
|
selectEntry: () => ({ match: false }),
|
|
});
|
|
|
|
expect(mocks.coreDrainPendingDeliveries).toHaveBeenCalledTimes(1);
|
|
const [{ deliver: lazyDeliver }] = expectDefined(
|
|
(mocks.coreDrainPendingDeliveries.mock.calls as unknown as Array<[{ deliver?: unknown }]>)[0],
|
|
"(mocks.coreDrainPendingDeliveries.mock.calls as unknown as Array<[{ deliver?: unknown }]>)[0] test invariant",
|
|
);
|
|
expect(lazyDeliver).toBe(mocks.deliverOutboundPayloads);
|
|
});
|
|
|
|
it("preserves an explicit deliver fn without loading the lazy runtime", async () => {
|
|
const deliver = vi.fn(async () => []);
|
|
|
|
await drainPendingDeliveries({
|
|
drainKey: "demo:test",
|
|
logLabel: "Demo reconnect drain",
|
|
cfg: {},
|
|
log,
|
|
deliver,
|
|
selectEntry: () => ({ match: false }),
|
|
});
|
|
|
|
expect(mocks.coreDrainPendingDeliveries).toHaveBeenCalledTimes(1);
|
|
const [{ deliver: explicitDeliver }] = expectDefined(
|
|
(mocks.coreDrainPendingDeliveries.mock.calls as unknown as Array<[{ deliver?: unknown }]>)[0],
|
|
"(mocks.coreDrainPendingDeliveries.mock.calls as unknown as Array<[{ deliver?: unknown }]>)[0] test invariant",
|
|
);
|
|
expect(explicitDeliver).toBe(deliver);
|
|
expect(mocks.deliverOutboundPayloads).not.toHaveBeenCalled();
|
|
});
|
|
});
|