Track HiveGrid Cloud planning reference
This commit is contained in:
1 parent
b3d5ea6764
commit
e341c5938a
5784 files changed
+1104929
-3
No files matched your search
@@ -0,0 +1,99 @@
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { MemoryAdapter, createSharedStore } from "@toolctrl/shared-store";
|
||||
|
||||
vi.mock("~/utils/cache.server", () => {
|
||||
const map = new Map<string, unknown>();
|
||||
return {
|
||||
cache: map,
|
||||
cachified: vi.fn(),
|
||||
clearCacheKey: vi.fn((key: string) => map.delete(key)),
|
||||
clearCacheKeyPrefix: vi.fn((prefix: string) => {
|
||||
for (const k of map.keys()) if (k.startsWith(prefix)) map.delete(k);
|
||||
}),
|
||||
__test_map: map,
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("~/shared-store.server", async () => {
|
||||
const { MemoryAdapter, createSharedStore } = await import("@toolctrl/shared-store");
|
||||
const adapter = new MemoryAdapter();
|
||||
const store = createSharedStore({ namespace: "web-test", adapter });
|
||||
return {
|
||||
getSharedStore: () => store,
|
||||
__setSharedStoreFactoryForTests: vi.fn(),
|
||||
__resetSharedStoreForTests: vi.fn(),
|
||||
};
|
||||
});
|
||||
|
||||
import {
|
||||
getSubscriptionCache,
|
||||
subscribeSubscriptionCache,
|
||||
__resetSubscriptionCacheForTests,
|
||||
} from "./subscriptionCache.server";
|
||||
import * as cacheServer from "~/utils/cache.server";
|
||||
|
||||
beforeEach(() => {
|
||||
__resetSubscriptionCacheForTests();
|
||||
// clear shared cache.server map between tests
|
||||
(cacheServer as unknown as { __test_map: Map<string, unknown> }).__test_map.clear();
|
||||
vi.mocked(cacheServer.clearCacheKey).mockClear();
|
||||
vi.mocked(cacheServer.clearCacheKeyPrefix).mockClear();
|
||||
delete process.env.CACHE_INVALIDATION_ENABLED;
|
||||
delete process.env.CACHE_L1_TTL_SECONDS;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
__resetSubscriptionCacheForTests();
|
||||
});
|
||||
|
||||
describe("subscription cache (two-tier)", () => {
|
||||
it("invalidate(tenantId) publishes + clears L2 and triggers local clearCacheKey via subscriber", async () => {
|
||||
const cache = getSubscriptionCache();
|
||||
await subscribeSubscriptionCache();
|
||||
await cache.invalidate("tenant-1");
|
||||
// Give the in-process pubsub event loop a tick to flush.
|
||||
await new Promise((r) => setTimeout(r, 10));
|
||||
expect(vi.mocked(cacheServer.clearCacheKey)).toHaveBeenCalledWith("tenantSubscription:tenant-1");
|
||||
});
|
||||
|
||||
it("wildcard invalidate clears the cachified prefix", async () => {
|
||||
const cache = getSubscriptionCache();
|
||||
await subscribeSubscriptionCache();
|
||||
await cache.invalidate();
|
||||
await new Promise((r) => setTimeout(r, 10));
|
||||
expect(vi.mocked(cacheServer.clearCacheKeyPrefix)).toHaveBeenCalledWith("tenantSubscription:");
|
||||
});
|
||||
|
||||
it("respects CACHE_INVALIDATION_ENABLED=false (subscribe is no-op, no publish)", async () => {
|
||||
process.env.CACHE_INVALIDATION_ENABLED = "false";
|
||||
__resetSubscriptionCacheForTests();
|
||||
const cache = getSubscriptionCache();
|
||||
const dispose = await subscribeSubscriptionCache();
|
||||
await cache.invalidate("tenant-2");
|
||||
await new Promise((r) => setTimeout(r, 10));
|
||||
// subscriber never wired because pubsub disabled → no clearCacheKey from remote path
|
||||
expect(vi.mocked(cacheServer.clearCacheKey)).not.toHaveBeenCalled();
|
||||
await dispose();
|
||||
});
|
||||
|
||||
it("subscribeSubscriptionCache is idempotent (returns same disposer)", async () => {
|
||||
const a = await subscribeSubscriptionCache();
|
||||
const b = await subscribeSubscriptionCache();
|
||||
expect(a).toBe(b);
|
||||
});
|
||||
|
||||
it("uses CACHE_L1_TTL_SECONDS override when present", async () => {
|
||||
process.env.CACHE_L1_TTL_SECONDS = "120";
|
||||
__resetSubscriptionCacheForTests();
|
||||
const cache = getSubscriptionCache();
|
||||
// Smoke: a set/get round-trip works with overridden TTL.
|
||||
await cache.set("t1", null);
|
||||
expect(await cache.get("t1")).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
// Silence the unused createSharedStore import — used only to load the package
|
||||
// (and force its types) for the mock factory above. vitest's mock factory is
|
||||
// hoisted so the dynamic import shape is the standard pattern here.
|
||||
void MemoryAdapter;
|
||||
void createSharedStore;
|
||||
Reference in new issue
Block a user