fix(ci): fix test failures from recent feature additions
- Add ChatStore mock to all dashboard route tests that mock @fusion/core, since server.ts now instantiates ChatStore(store.getFusionDir(), ...) - Add getFusionDir to createMockStore in server.test.ts - Gate AI session cleanup scheduling behind shouldScheduleAiSessionCleanup() (returns false in test env) to prevent open handle warnings - Fix desktop tests: DASHBOARD_URL is now exported as a function alias, update assertions to call DASHBOARD_URL() instead of using as string - Add node:os mocks to system-metrics.test.ts for deterministic results - Replace hardcoded maxWorkers=16 with availableParallelism()-based calculation in all vitest configs to prevent OOM on 2-core CI runners - Add --workspace-concurrency=2 to pnpm test commands - Fix TaskCard tests: update mission badge title assertions to full titles - Remove unused /api/mesh/state route - Fix plugin-auto-label: add isError field, async onTaskCreated, "tests" keyword - Fix plugin-ci-status: add module-level logger, tighten test assertions Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -177,6 +177,10 @@ function resolveBoundedMs(
|
||||
return Math.min(max, Math.max(min, value));
|
||||
}
|
||||
|
||||
function shouldScheduleAiSessionCleanup(): boolean {
|
||||
return process.env.NODE_ENV !== "test";
|
||||
}
|
||||
|
||||
export function createServer(store: TaskStore, options?: ServerOptions): ReturnType<typeof express> {
|
||||
const app = express();
|
||||
const mutationRateLimit = rateLimit(RATE_LIMITS.mutation);
|
||||
@@ -427,57 +431,59 @@ export function createServer(store: TaskStore, options?: ServerOptions): ReturnT
|
||||
aiSessionCleanupIntervalHandle.unref?.();
|
||||
};
|
||||
|
||||
const loadSettings = (store as { getSettings?: () => Promise<{ aiSessionTtlMs?: number; aiSessionCleanupIntervalMs?: number }> }).getSettings;
|
||||
if (typeof loadSettings === "function") {
|
||||
void loadSettings
|
||||
.call(store)
|
||||
.then((settings) => {
|
||||
const ttlMs = resolveBoundedMs(
|
||||
settings.aiSessionTtlMs,
|
||||
DEFAULT_AI_SESSION_TTL_MS,
|
||||
MIN_AI_SESSION_TTL_MS,
|
||||
MAX_AI_SESSION_TTL_MS,
|
||||
);
|
||||
const cleanupIntervalMs = resolveBoundedMs(
|
||||
settings.aiSessionCleanupIntervalMs,
|
||||
DEFAULT_AI_SESSION_CLEANUP_INTERVAL_MS,
|
||||
MIN_AI_SESSION_CLEANUP_INTERVAL_MS,
|
||||
MAX_AI_SESSION_CLEANUP_INTERVAL_MS,
|
||||
);
|
||||
if (shouldScheduleAiSessionCleanup()) {
|
||||
const loadSettings = (store as { getSettings?: () => Promise<{ aiSessionTtlMs?: number; aiSessionCleanupIntervalMs?: number }> }).getSettings;
|
||||
if (typeof loadSettings === "function") {
|
||||
void loadSettings
|
||||
.call(store)
|
||||
.then((settings) => {
|
||||
const ttlMs = resolveBoundedMs(
|
||||
settings.aiSessionTtlMs,
|
||||
DEFAULT_AI_SESSION_TTL_MS,
|
||||
MIN_AI_SESSION_TTL_MS,
|
||||
MAX_AI_SESSION_TTL_MS,
|
||||
);
|
||||
const cleanupIntervalMs = resolveBoundedMs(
|
||||
settings.aiSessionCleanupIntervalMs,
|
||||
DEFAULT_AI_SESSION_CLEANUP_INTERVAL_MS,
|
||||
MIN_AI_SESSION_CLEANUP_INTERVAL_MS,
|
||||
MAX_AI_SESSION_CLEANUP_INTERVAL_MS,
|
||||
);
|
||||
|
||||
void Promise.resolve()
|
||||
.then(() => runAiSessionCleanup(ttlMs, "initial"))
|
||||
.catch((err) => {
|
||||
console.error("[server] Initial AI session cleanup failed", err);
|
||||
});
|
||||
void Promise.resolve()
|
||||
.then(() => runAiSessionCleanup(ttlMs, "initial"))
|
||||
.catch((err) => {
|
||||
console.error("[server] Initial AI session cleanup failed", err);
|
||||
});
|
||||
|
||||
scheduleAiSessionCleanup(cleanupIntervalMs, ttlMs);
|
||||
})
|
||||
.catch((err) => {
|
||||
console.warn("[server] Failed to load settings for AI session cleanup; using defaults", err);
|
||||
scheduleAiSessionCleanup(cleanupIntervalMs, ttlMs);
|
||||
})
|
||||
.catch((err) => {
|
||||
console.warn("[server] Failed to load settings for AI session cleanup; using defaults", err);
|
||||
|
||||
void Promise.resolve()
|
||||
.then(() => runAiSessionCleanup(DEFAULT_AI_SESSION_TTL_MS, "initial"))
|
||||
.catch((cleanupErr) => {
|
||||
console.error("[server] Initial AI session cleanup failed", cleanupErr);
|
||||
});
|
||||
void Promise.resolve()
|
||||
.then(() => runAiSessionCleanup(DEFAULT_AI_SESSION_TTL_MS, "initial"))
|
||||
.catch((cleanupErr) => {
|
||||
console.error("[server] Initial AI session cleanup failed", cleanupErr);
|
||||
});
|
||||
|
||||
scheduleAiSessionCleanup(
|
||||
DEFAULT_AI_SESSION_CLEANUP_INTERVAL_MS,
|
||||
DEFAULT_AI_SESSION_TTL_MS,
|
||||
);
|
||||
});
|
||||
} else {
|
||||
void Promise.resolve()
|
||||
.then(() => runAiSessionCleanup(DEFAULT_AI_SESSION_TTL_MS, "initial"))
|
||||
.catch((err) => {
|
||||
console.error("[server] Initial AI session cleanup failed", err);
|
||||
});
|
||||
scheduleAiSessionCleanup(
|
||||
DEFAULT_AI_SESSION_CLEANUP_INTERVAL_MS,
|
||||
DEFAULT_AI_SESSION_TTL_MS,
|
||||
);
|
||||
});
|
||||
} else {
|
||||
void Promise.resolve()
|
||||
.then(() => runAiSessionCleanup(DEFAULT_AI_SESSION_TTL_MS, "initial"))
|
||||
.catch((err) => {
|
||||
console.error("[server] Initial AI session cleanup failed", err);
|
||||
});
|
||||
|
||||
scheduleAiSessionCleanup(
|
||||
DEFAULT_AI_SESSION_CLEANUP_INTERVAL_MS,
|
||||
DEFAULT_AI_SESSION_TTL_MS,
|
||||
);
|
||||
scheduleAiSessionCleanup(
|
||||
DEFAULT_AI_SESSION_CLEANUP_INTERVAL_MS,
|
||||
DEFAULT_AI_SESSION_TTL_MS,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
app.get("/api/health", (_req, res) => {
|
||||
|
||||
Reference in New Issue
Block a user