diff --git a/apps/sim/lib/copilot/chat/payload.ts b/apps/sim/lib/copilot/chat/payload.ts index 1c882f3d4d1..691d30ecb06 100644 --- a/apps/sim/lib/copilot/chat/payload.ts +++ b/apps/sim/lib/copilot/chat/payload.ts @@ -5,6 +5,7 @@ import { isPaid } from '@/lib/billing/plan-helpers' import { getToolEntry } from '@/lib/copilot/tool-executor/router' import { getCopilotToolDescription } from '@/lib/copilot/tools/descriptions' import { isHosted } from '@/lib/core/config/feature-flags' +import { registerCache } from '@/lib/monitoring/cache-registry' import { buildMothershipToolsForRequest } from '@/lib/mothership/settings/runtime' import { trackChatUpload } from '@/lib/uploads/contexts/workspace/workspace-file-manager' import { tools } from '@/tools/registry' @@ -21,6 +22,15 @@ type ToolSchemaCacheEntry = { const toolSchemaCache = new Map() +setInterval(() => { + const now = Date.now() + for (const [key, entry] of toolSchemaCache) { + if (entry.expiresAt <= now) toolSchemaCache.delete(key) + } +}, TOOL_SCHEMA_CACHE_TTL_MS).unref() + +registerCache('toolSchemaCache', () => toolSchemaCache.size) + interface BuildPayloadParams { message: string workflowId?: string diff --git a/apps/sim/lib/core/async-jobs/backends/database.ts b/apps/sim/lib/core/async-jobs/backends/database.ts index afaa44a3641..edbcd3d8b4a 100644 --- a/apps/sim/lib/core/async-jobs/backends/database.ts +++ b/apps/sim/lib/core/async-jobs/backends/database.ts @@ -38,6 +38,7 @@ function rowToJob(row: AsyncJobRow): Job { const inlineAbortControllers = new Map() interface Semaphore { + limit: number available: number waiters: Array<() => void> } @@ -46,7 +47,7 @@ const semaphores = new Map() async function acquireSlot(key: string, limit: number): Promise { let s = semaphores.get(key) if (!s) { - s = { available: limit, waiters: [] } + s = { limit, available: limit, waiters: [] } semaphores.set(key, s) } if (s.available > 0) { @@ -65,6 +66,9 @@ function releaseSlot(key: string): void { return } s.available += 1 + if (s.waiters.length === 0 && s.available === s.limit) { + semaphores.delete(key) + } } export class DatabaseJobQueue implements JobQueueBackend { diff --git a/apps/sim/lib/environment/utils.ts b/apps/sim/lib/environment/utils.ts index 509dcfd7667..e3e4c38753d 100644 --- a/apps/sim/lib/environment/utils.ts +++ b/apps/sim/lib/environment/utils.ts @@ -10,6 +10,7 @@ import { getAccessibleEnvCredentials, syncPersonalEnvCredentialsForUser, } from '@/lib/credentials/environment' +import { registerCache } from '@/lib/monitoring/cache-registry' import { checkWorkspaceAccess } from '@/lib/workspaces/permissions/utils' const logger = createLogger('EnvironmentUtils') @@ -23,6 +24,15 @@ type EffectiveEnvCacheEntry = { const effectiveEnvCache = new Map() +setInterval(() => { + const now = Date.now() + for (const [key, entry] of effectiveEnvCache) { + if (!entry.promise && entry.expiresAt <= now) effectiveEnvCache.delete(key) + } +}, EFFECTIVE_ENV_CACHE_TTL_MS).unref() + +registerCache('effectiveEnvCache', () => effectiveEnvCache.size) + function getEffectiveEnvCacheKey(userId: string, workspaceId?: string) { return `${userId}:${workspaceId ?? ''}` } diff --git a/apps/sim/lib/monitoring/cache-registry.ts b/apps/sim/lib/monitoring/cache-registry.ts new file mode 100644 index 00000000000..19b8753b444 --- /dev/null +++ b/apps/sim/lib/monitoring/cache-registry.ts @@ -0,0 +1,13 @@ +const registry = new Map number>() + +export function registerCache(name: string, getSize: () => number): void { + registry.set(name, getSize) +} + +export function getCacheSizes(): Record { + const sizes: Record = {} + for (const [name, getSize] of registry) { + sizes[name] = getSize() + } + return sizes +} diff --git a/apps/sim/lib/monitoring/memory-telemetry.ts b/apps/sim/lib/monitoring/memory-telemetry.ts index 2845ee1def2..f80a0189dce 100644 --- a/apps/sim/lib/monitoring/memory-telemetry.ts +++ b/apps/sim/lib/monitoring/memory-telemetry.ts @@ -5,6 +5,7 @@ import v8 from 'node:v8' import { createLogger } from '@sim/logger' +import { getCacheSizes } from '@/lib/monitoring/cache-registry' const logger = createLogger('MemoryTelemetry', { logLevel: 'INFO' }) @@ -33,6 +34,7 @@ export function startMemoryTelemetry(intervalMs = 60_000) { ? process.getActiveResourcesInfo().length : -1, uptimeMin: Math.round(process.uptime() / 60), + cacheSizes: getCacheSizes(), }) }, intervalMs) timer.unref()