@stackmemoryai/stackmemory 0.2.8 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents/core/agent-task-manager.js +512 -0
- package/dist/agents/core/agent-task-manager.js.map +7 -0
- package/dist/agents/verifiers/base-verifier.js +129 -0
- package/dist/agents/verifiers/base-verifier.js.map +7 -0
- package/dist/agents/verifiers/formatter-verifier.js +126 -0
- package/dist/agents/verifiers/formatter-verifier.js.map +7 -0
- package/dist/agents/verifiers/llm-judge.js +248 -0
- package/dist/agents/verifiers/llm-judge.js.map +7 -0
- package/dist/cli/__tests__/index.test.js +290 -0
- package/dist/cli/__tests__/index.test.js.map +7 -0
- package/dist/cli/auto-detect.js +317 -0
- package/dist/cli/auto-detect.js.map +7 -0
- package/dist/cli/browser-test.js +29 -0
- package/dist/cli/browser-test.js.map +7 -0
- package/dist/cli/claude-sm.js +369 -0
- package/dist/cli/claude-sm.js.map +7 -0
- package/dist/cli/codex-sm.js +283 -0
- package/dist/cli/codex-sm.js.map +7 -0
- package/dist/cli/commands/agent.js +286 -0
- package/dist/cli/commands/agent.js.map +7 -0
- package/dist/cli/commands/config.js +199 -0
- package/dist/cli/commands/config.js.map +7 -0
- package/dist/cli/commands/context.js +327 -0
- package/dist/cli/commands/context.js.map +7 -0
- package/dist/cli/commands/handoff.js +191 -0
- package/dist/cli/commands/handoff.js.map +7 -0
- package/dist/cli/commands/linear-test.js +115 -0
- package/dist/cli/commands/linear-test.js.map +7 -0
- package/dist/cli/commands/linear.js +378 -0
- package/dist/cli/commands/linear.js.map +7 -0
- package/dist/cli/commands/log.js +165 -0
- package/dist/cli/commands/log.js.map +7 -0
- package/dist/cli/commands/onboard.js +349 -0
- package/dist/cli/commands/onboard.js.map +7 -0
- package/dist/cli/commands/projects.js +195 -0
- package/dist/cli/commands/projects.js.map +7 -0
- package/dist/cli/commands/search.js +152 -0
- package/dist/cli/commands/search.js.map +7 -0
- package/dist/cli/commands/session.js +179 -0
- package/dist/cli/commands/session.js.map +7 -0
- package/dist/cli/commands/tasks.js +205 -0
- package/dist/cli/commands/tasks.js.map +7 -0
- package/dist/cli/commands/webhook.js +131 -0
- package/dist/cli/commands/webhook.js.map +7 -0
- package/dist/cli/commands/worktree.js +276 -0
- package/dist/cli/commands/worktree.js.map +7 -0
- package/dist/cli/index.js +953 -0
- package/dist/cli/index.js.map +7 -0
- package/dist/cli/utils/viewer.js +92 -0
- package/dist/cli/utils/viewer.js.map +7 -0
- package/dist/core/config/__tests__/config-manager.test.js +248 -0
- package/dist/core/config/__tests__/config-manager.test.js.map +7 -0
- package/dist/core/config/config-manager.js +368 -0
- package/dist/core/config/config-manager.js.map +7 -0
- package/dist/core/config/types.js +140 -0
- package/dist/core/config/types.js.map +7 -0
- package/dist/core/context/__tests__/frame-manager.test.js +879 -0
- package/dist/core/context/__tests__/frame-manager.test.js.map +7 -0
- package/dist/core/context/auto-context.js +72 -0
- package/dist/core/context/auto-context.js.map +7 -0
- package/dist/core/context/compaction-handler.js +326 -0
- package/dist/core/context/compaction-handler.js.map +7 -0
- package/dist/core/context/frame-database.js +376 -0
- package/dist/core/context/frame-database.js.map +7 -0
- package/dist/core/context/frame-digest.js +239 -0
- package/dist/core/context/frame-digest.js.map +7 -0
- package/dist/core/context/frame-manager.js +682 -0
- package/dist/core/context/frame-manager.js.map +7 -0
- package/dist/core/context/frame-stack.js +270 -0
- package/dist/core/context/frame-stack.js.map +7 -0
- package/dist/core/context/frame-types.js +1 -0
- package/dist/core/context/frame-types.js.map +7 -0
- package/dist/core/context/index.js +33 -0
- package/dist/core/context/index.js.map +7 -0
- package/dist/core/context/model-aware-compaction.js +619 -0
- package/dist/core/context/model-aware-compaction.js.map +7 -0
- package/dist/core/context/refactored-frame-manager.js +393 -0
- package/dist/core/context/refactored-frame-manager.js.map +7 -0
- package/dist/core/database/batch-operations.js +329 -0
- package/dist/core/database/batch-operations.js.map +7 -0
- package/dist/core/database/connection-pool.js +224 -0
- package/dist/core/database/connection-pool.js.map +7 -0
- package/dist/core/database/query-cache.js +284 -0
- package/dist/core/database/query-cache.js.map +7 -0
- package/dist/core/digest/__tests__/enhanced-hybrid-digest.test.js +379 -0
- package/dist/core/digest/__tests__/enhanced-hybrid-digest.test.js.map +7 -0
- package/dist/core/digest/__tests__/frame-digest-integration.test.js +230 -0
- package/dist/core/digest/__tests__/frame-digest-integration.test.js.map +7 -0
- package/dist/core/digest/enhanced-hybrid-digest.js +267 -0
- package/dist/core/digest/enhanced-hybrid-digest.js.map +7 -0
- package/dist/core/digest/frame-digest-integration.js +172 -0
- package/dist/core/digest/frame-digest-integration.js.map +7 -0
- package/dist/core/digest/hybrid-digest-generator.js +549 -0
- package/dist/core/digest/hybrid-digest-generator.js.map +7 -0
- package/dist/core/digest/index.js +5 -0
- package/dist/core/digest/index.js.map +7 -0
- package/dist/core/digest/types.js +21 -0
- package/dist/core/digest/types.js.map +7 -0
- package/dist/core/errors/__tests__/error-handling.test.js +270 -0
- package/dist/core/errors/__tests__/error-handling.test.js.map +7 -0
- package/dist/core/errors/index.js +239 -0
- package/dist/core/errors/index.js.map +7 -0
- package/dist/core/errors/recovery.js +258 -0
- package/dist/core/errors/recovery.js.map +7 -0
- package/dist/core/merge/__tests__/conflict-scenarios.test.js +414 -0
- package/dist/core/merge/__tests__/conflict-scenarios.test.js.map +7 -0
- package/dist/core/merge/conflict-detector.js +424 -0
- package/dist/core/merge/conflict-detector.js.map +7 -0
- package/dist/core/merge/index.js +5 -0
- package/dist/core/merge/index.js.map +7 -0
- package/dist/core/merge/resolution-engine.js +565 -0
- package/dist/core/merge/resolution-engine.js.map +7 -0
- package/dist/core/merge/stack-diff.js +528 -0
- package/dist/core/merge/stack-diff.js.map +7 -0
- package/dist/core/merge/types.js +1 -0
- package/dist/core/merge/types.js.map +7 -0
- package/dist/core/monitoring/error-handler.js +278 -0
- package/dist/core/monitoring/error-handler.js.map +7 -0
- package/dist/core/monitoring/logger.js +115 -0
- package/dist/core/monitoring/logger.js.map +7 -0
- package/dist/core/monitoring/metrics.js +157 -0
- package/dist/core/monitoring/metrics.js.map +7 -0
- package/dist/core/monitoring/progress-tracker.js +174 -0
- package/dist/core/monitoring/progress-tracker.js.map +7 -0
- package/dist/core/performance/context-cache.js +269 -0
- package/dist/core/performance/context-cache.js.map +7 -0
- package/dist/core/performance/index.js +7 -0
- package/dist/core/performance/index.js.map +7 -0
- package/dist/core/performance/lazy-context-loader.js +319 -0
- package/dist/core/performance/lazy-context-loader.js.map +7 -0
- package/dist/core/performance/monitor.js +217 -0
- package/dist/core/performance/monitor.js.map +7 -0
- package/dist/core/performance/optimized-frame-context.js +326 -0
- package/dist/core/performance/optimized-frame-context.js.map +7 -0
- package/dist/core/performance/performance-benchmark.js +269 -0
- package/dist/core/performance/performance-benchmark.js.map +7 -0
- package/dist/core/performance/performance-profiler.js +318 -0
- package/dist/core/performance/performance-profiler.js.map +7 -0
- package/dist/core/performance/streaming-jsonl-parser.js +187 -0
- package/dist/core/performance/streaming-jsonl-parser.js.map +7 -0
- package/dist/core/persistence/postgres-adapter.js +345 -0
- package/dist/core/persistence/postgres-adapter.js.map +7 -0
- package/dist/core/projects/project-manager.js +699 -0
- package/dist/core/projects/project-manager.js.map +7 -0
- package/dist/core/query/__tests__/query-parser.test.js +301 -0
- package/dist/core/query/__tests__/query-parser.test.js.map +7 -0
- package/dist/core/query/__tests__/query-templates.test.js +210 -0
- package/dist/core/query/__tests__/query-templates.test.js.map +7 -0
- package/dist/core/query/query-parser.js +366 -0
- package/dist/core/query/query-parser.js.map +7 -0
- package/dist/core/query/query-templates.js +317 -0
- package/dist/core/query/query-templates.js.map +7 -0
- package/dist/core/retrieval/index.js +4 -0
- package/dist/core/retrieval/index.js.map +7 -0
- package/dist/core/retrieval/llm-context-retrieval.js +577 -0
- package/dist/core/retrieval/llm-context-retrieval.js.map +7 -0
- package/dist/core/retrieval/summary-generator.js +585 -0
- package/dist/core/retrieval/summary-generator.js.map +7 -0
- package/dist/core/retrieval/types.js +17 -0
- package/dist/core/retrieval/types.js.map +7 -0
- package/dist/core/session/index.js +11 -0
- package/dist/core/session/index.js.map +7 -0
- package/dist/core/session/session-manager.js +297 -0
- package/dist/core/session/session-manager.js.map +7 -0
- package/dist/core/trace/cli-trace-wrapper.js +110 -0
- package/dist/core/trace/cli-trace-wrapper.js.map +7 -0
- package/dist/core/trace/db-trace-wrapper.js +215 -0
- package/dist/core/trace/db-trace-wrapper.js.map +7 -0
- package/dist/core/trace/debug-trace.js +385 -0
- package/dist/core/trace/debug-trace.js.map +7 -0
- package/dist/core/trace/index.js +158 -0
- package/dist/core/trace/index.js.map +7 -0
- package/dist/core/trace/linear-api-wrapper.js +169 -0
- package/dist/core/trace/linear-api-wrapper.js.map +7 -0
- package/dist/core/trace/trace-demo.js +135 -0
- package/dist/core/trace/trace-demo.js.map +7 -0
- package/dist/core/trace/trace-detector.demo.js +138 -0
- package/dist/core/trace/trace-detector.demo.js.map +7 -0
- package/dist/core/trace/trace-detector.js +386 -0
- package/dist/core/trace/trace-detector.js.map +7 -0
- package/dist/core/trace/trace-detector.test.js +401 -0
- package/dist/core/trace/trace-detector.test.js.map +7 -0
- package/dist/core/trace/trace-store.js +341 -0
- package/dist/core/trace/trace-store.js.map +7 -0
- package/dist/core/trace/types.js +73 -0
- package/dist/core/trace/types.js.map +7 -0
- package/dist/core/types.js +1 -0
- package/dist/core/types.js.map +7 -0
- package/dist/core/utils/update-checker.js +214 -0
- package/dist/core/utils/update-checker.js.map +7 -0
- package/dist/core/worktree/worktree-manager.js +450 -0
- package/dist/core/worktree/worktree-manager.js.map +7 -0
- package/dist/features/analytics/api/analytics-api.js +283 -0
- package/dist/features/analytics/api/analytics-api.js.map +7 -0
- package/dist/features/analytics/core/analytics-service.js +267 -0
- package/dist/features/analytics/core/analytics-service.js.map +7 -0
- package/dist/features/analytics/index.js +14 -0
- package/dist/features/analytics/index.js.map +7 -0
- package/dist/features/analytics/queries/metrics-queries.js +273 -0
- package/dist/features/analytics/queries/metrics-queries.js.map +7 -0
- package/dist/features/analytics/types/metrics.js +1 -0
- package/dist/features/analytics/types/metrics.js.map +7 -0
- package/dist/features/browser/browser-mcp.js +488 -0
- package/dist/features/browser/browser-mcp.js.map +7 -0
- package/dist/features/tasks/__tests__/pebbles-task-store.test.js +747 -0
- package/dist/features/tasks/__tests__/pebbles-task-store.test.js.map +7 -0
- package/dist/features/tasks/pebbles-task-store.js +647 -0
- package/dist/features/tasks/pebbles-task-store.js.map +7 -0
- package/dist/features/tasks/task-aware-context.js +406 -0
- package/dist/features/tasks/task-aware-context.js.map +7 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +7 -0
- package/dist/integrations/linear/__tests__/auth.test.js +558 -0
- package/dist/integrations/linear/__tests__/auth.test.js.map +7 -0
- package/dist/integrations/linear/__tests__/sync-service.test.js +760 -0
- package/dist/integrations/linear/__tests__/sync-service.test.js.map +7 -0
- package/dist/integrations/linear/auth.js +308 -0
- package/dist/integrations/linear/auth.js.map +7 -0
- package/dist/integrations/linear/auto-sync.js +244 -0
- package/dist/integrations/linear/auto-sync.js.map +7 -0
- package/dist/integrations/linear/client.js +448 -0
- package/dist/integrations/linear/client.js.map +7 -0
- package/dist/integrations/linear/config.js +115 -0
- package/dist/integrations/linear/config.js.map +7 -0
- package/dist/integrations/linear/sync-manager.js +233 -0
- package/dist/integrations/linear/sync-manager.js.map +7 -0
- package/dist/integrations/linear/sync-service.js +214 -0
- package/dist/integrations/linear/sync-service.js.map +7 -0
- package/dist/integrations/linear/sync.js +565 -0
- package/dist/integrations/linear/sync.js.map +7 -0
- package/dist/integrations/linear/types.js +1 -0
- package/dist/integrations/linear/types.js.map +7 -0
- package/dist/integrations/linear/webhook-server.js +204 -0
- package/dist/integrations/linear/webhook-server.js.map +7 -0
- package/dist/integrations/linear/webhook.js +269 -0
- package/dist/integrations/linear/webhook.js.map +7 -0
- package/dist/integrations/mcp/__tests__/server.test.js +798 -0
- package/dist/integrations/mcp/__tests__/server.test.js.map +7 -0
- package/dist/integrations/mcp/handlers/context-handlers.js +253 -0
- package/dist/integrations/mcp/handlers/context-handlers.js.map +7 -0
- package/dist/integrations/mcp/handlers/index.js +134 -0
- package/dist/integrations/mcp/handlers/index.js.map +7 -0
- package/dist/integrations/mcp/handlers/linear-handlers.js +243 -0
- package/dist/integrations/mcp/handlers/linear-handlers.js.map +7 -0
- package/dist/integrations/mcp/handlers/task-handlers.js +235 -0
- package/dist/integrations/mcp/handlers/task-handlers.js.map +7 -0
- package/dist/integrations/mcp/handlers/trace-handlers.js +304 -0
- package/dist/integrations/mcp/handlers/trace-handlers.js.map +7 -0
- package/dist/integrations/mcp/index.js +19 -0
- package/dist/integrations/mcp/index.js.map +7 -0
- package/dist/integrations/mcp/refactored-server.js +331 -0
- package/dist/integrations/mcp/refactored-server.js.map +7 -0
- package/dist/integrations/mcp/server.js +1621 -0
- package/dist/integrations/mcp/server.js.map +7 -0
- package/dist/integrations/mcp/tool-definitions.js +562 -0
- package/dist/integrations/mcp/tool-definitions.js.map +7 -0
- package/dist/integrations/mcp/trace-test.js +44 -0
- package/dist/integrations/mcp/trace-test.js.map +7 -0
- package/dist/integrations/pg-aiguide/embedding-provider.js +174 -0
- package/dist/integrations/pg-aiguide/embedding-provider.js.map +7 -0
- package/dist/integrations/pg-aiguide/semantic-search.js +183 -0
- package/dist/integrations/pg-aiguide/semantic-search.js.map +7 -0
- package/dist/integrations/pg-aiguide/timescale-analytics.js +220 -0
- package/dist/integrations/pg-aiguide/timescale-analytics.js.map +7 -0
- package/dist/mcp/stackmemory-mcp-server.js +550 -0
- package/dist/mcp/stackmemory-mcp-server.js.map +7 -0
- package/dist/middleware/exponential-rate-limiter.js +285 -0
- package/dist/middleware/exponential-rate-limiter.js.map +7 -0
- package/dist/models/user.model.js +351 -0
- package/dist/models/user.model.js.map +7 -0
- package/dist/scripts/benchmark-performance.d.ts +7 -0
- package/dist/scripts/benchmark-performance.d.ts.map +1 -0
- package/dist/scripts/benchmark-performance.js +44 -0
- package/dist/scripts/benchmark-performance.js.map +1 -0
- package/dist/scripts/cleanup-duplicate-tasks.d.ts +12 -0
- package/dist/scripts/cleanup-duplicate-tasks.d.ts.map +1 -0
- package/dist/scripts/cleanup-duplicate-tasks.js +215 -0
- package/dist/scripts/cleanup-duplicate-tasks.js.map +1 -0
- package/dist/servers/production/auth-middleware.js +513 -0
- package/dist/servers/production/auth-middleware.js.map +7 -0
- package/dist/servers/railway/index.js +390 -0
- package/dist/servers/railway/index.js.map +7 -0
- package/dist/services/config-service.js +62 -0
- package/dist/services/config-service.js.map +7 -0
- package/dist/services/context-service.js +191 -0
- package/dist/services/context-service.js.map +7 -0
- package/dist/src/agents/core/agent-task-manager.d.ts +154 -0
- package/dist/src/agents/core/agent-task-manager.d.ts.map +1 -0
- package/dist/src/agents/core/agent-task-manager.js +504 -0
- package/dist/src/agents/core/agent-task-manager.js.map +1 -0
- package/dist/src/agents/verifiers/base-verifier.d.ts +112 -0
- package/dist/src/agents/verifiers/base-verifier.d.ts.map +1 -0
- package/dist/src/agents/verifiers/base-verifier.js +130 -0
- package/dist/src/agents/verifiers/base-verifier.js.map +1 -0
- package/dist/src/agents/verifiers/formatter-verifier.d.ts +14 -0
- package/dist/src/agents/verifiers/formatter-verifier.d.ts.map +1 -0
- package/dist/src/agents/verifiers/formatter-verifier.js +107 -0
- package/dist/src/agents/verifiers/formatter-verifier.js.map +1 -0
- package/dist/src/agents/verifiers/llm-judge.d.ts +46 -0
- package/dist/src/agents/verifiers/llm-judge.d.ts.map +1 -0
- package/dist/src/agents/verifiers/llm-judge.js +248 -0
- package/dist/src/agents/verifiers/llm-judge.js.map +1 -0
- package/dist/src/cli/claude-sm.js +55 -0
- package/dist/src/cli/claude-sm.js.map +1 -1
- package/dist/src/cli/commands/agent.d.ts +9 -0
- package/dist/src/cli/commands/agent.d.ts.map +1 -0
- package/dist/src/cli/commands/agent.js +303 -0
- package/dist/src/cli/commands/agent.js.map +1 -0
- package/dist/src/cli/commands/handoff.d.ts +6 -0
- package/dist/src/cli/commands/handoff.d.ts.map +1 -0
- package/dist/src/cli/commands/handoff.js +212 -0
- package/dist/src/cli/commands/handoff.js.map +1 -0
- package/dist/src/cli/index.d.ts.map +1 -1
- package/dist/src/cli/index.js +4 -0
- package/dist/src/cli/index.js.map +1 -1
- package/dist/src/core/context/compaction-handler.d.ts.map +1 -1
- package/dist/src/core/context/compaction-handler.js +1 -1
- package/dist/src/core/context/compaction-handler.js.map +1 -1
- package/dist/src/core/context/frame-database.d.ts +59 -0
- package/dist/src/core/context/frame-database.d.ts.map +1 -0
- package/dist/src/core/context/frame-database.js +333 -0
- package/dist/src/core/context/frame-database.js.map +1 -0
- package/dist/src/core/context/frame-digest.d.ts +59 -0
- package/dist/src/core/context/frame-digest.d.ts.map +1 -0
- package/dist/src/core/context/frame-digest.js +264 -0
- package/dist/src/core/context/frame-digest.js.map +1 -0
- package/dist/src/core/context/frame-manager.d.ts +2 -0
- package/dist/src/core/context/frame-manager.d.ts.map +1 -1
- package/dist/src/core/context/frame-manager.js +7 -0
- package/dist/src/core/context/frame-manager.js.map +1 -1
- package/dist/src/core/context/frame-stack.d.ts +85 -0
- package/dist/src/core/context/frame-stack.d.ts.map +1 -0
- package/dist/src/core/context/frame-stack.js +287 -0
- package/dist/src/core/context/frame-stack.js.map +1 -0
- package/dist/src/core/context/frame-types.d.ts +67 -0
- package/dist/src/core/context/frame-types.d.ts.map +1 -0
- package/dist/src/core/context/frame-types.js +6 -0
- package/dist/src/core/context/frame-types.js.map +1 -0
- package/dist/src/core/context/index.d.ts +11 -0
- package/dist/src/core/context/index.d.ts.map +1 -0
- package/dist/src/core/context/index.js +14 -0
- package/dist/src/core/context/index.js.map +1 -0
- package/dist/src/core/context/refactored-frame-manager.d.ts +99 -0
- package/dist/src/core/context/refactored-frame-manager.d.ts.map +1 -0
- package/dist/src/core/context/refactored-frame-manager.js +340 -0
- package/dist/src/core/context/refactored-frame-manager.js.map +1 -0
- package/dist/src/core/database/batch-operations.d.ts +118 -0
- package/dist/src/core/database/batch-operations.d.ts.map +1 -0
- package/dist/src/core/database/batch-operations.js +339 -0
- package/dist/src/core/database/batch-operations.js.map +1 -0
- package/dist/src/core/database/connection-pool.d.ts +79 -0
- package/dist/src/core/database/connection-pool.d.ts.map +1 -0
- package/dist/src/core/database/connection-pool.js +236 -0
- package/dist/src/core/database/connection-pool.js.map +1 -0
- package/dist/src/core/database/query-cache.d.ts +135 -0
- package/dist/src/core/database/query-cache.d.ts.map +1 -0
- package/dist/src/core/database/query-cache.js +294 -0
- package/dist/src/core/database/query-cache.js.map +1 -0
- package/dist/src/core/digest/enhanced-hybrid-digest.d.ts +125 -0
- package/dist/src/core/digest/enhanced-hybrid-digest.d.ts.map +1 -0
- package/dist/src/core/digest/enhanced-hybrid-digest.js +282 -0
- package/dist/src/core/digest/enhanced-hybrid-digest.js.map +1 -0
- package/dist/src/core/digest/frame-digest-integration.d.ts +67 -0
- package/dist/src/core/digest/frame-digest-integration.d.ts.map +1 -0
- package/dist/src/core/digest/frame-digest-integration.js +198 -0
- package/dist/src/core/digest/frame-digest-integration.js.map +1 -0
- package/dist/src/core/digest/hybrid-digest-generator.d.ts +76 -0
- package/dist/src/core/digest/hybrid-digest-generator.d.ts.map +1 -0
- package/dist/src/core/digest/hybrid-digest-generator.js +629 -0
- package/dist/src/core/digest/hybrid-digest-generator.js.map +1 -0
- package/dist/src/core/digest/index.d.ts +9 -0
- package/dist/src/core/digest/index.d.ts.map +1 -0
- package/dist/src/core/digest/index.js +9 -0
- package/dist/src/core/digest/index.js.map +1 -0
- package/dist/src/core/digest/types.d.ts +154 -0
- package/dist/src/core/digest/types.d.ts.map +1 -0
- package/dist/src/core/digest/types.js +18 -0
- package/dist/src/core/digest/types.js.map +1 -0
- package/dist/src/core/errors/index.d.ts +13 -5
- package/dist/src/core/errors/index.d.ts.map +1 -1
- package/dist/src/core/errors/index.js +13 -5
- package/dist/src/core/errors/index.js.map +1 -1
- package/dist/src/core/merge/conflict-detector.d.ts +122 -0
- package/dist/src/core/merge/conflict-detector.d.ts.map +1 -0
- package/dist/src/core/merge/conflict-detector.js +468 -0
- package/dist/src/core/merge/conflict-detector.js.map +1 -0
- package/dist/src/core/merge/index.d.ts +9 -0
- package/dist/src/core/merge/index.d.ts.map +1 -0
- package/dist/src/core/merge/index.js +9 -0
- package/dist/src/core/merge/index.js.map +1 -0
- package/dist/src/core/merge/resolution-engine.d.ts +120 -0
- package/dist/src/core/merge/resolution-engine.d.ts.map +1 -0
- package/dist/src/core/merge/resolution-engine.js +573 -0
- package/dist/src/core/merge/resolution-engine.js.map +1 -0
- package/dist/src/core/merge/stack-diff.d.ts +97 -0
- package/dist/src/core/merge/stack-diff.d.ts.map +1 -0
- package/dist/src/core/merge/stack-diff.js +516 -0
- package/dist/src/core/merge/stack-diff.js.map +1 -0
- package/dist/src/core/merge/types.d.ts +110 -0
- package/dist/src/core/merge/types.d.ts.map +1 -0
- package/dist/src/core/merge/types.js +6 -0
- package/dist/src/core/merge/types.js.map +1 -0
- package/dist/src/core/monitoring/logger.d.ts +2 -2
- package/dist/src/core/monitoring/logger.d.ts.map +1 -1
- package/dist/src/core/monitoring/logger.js +10 -5
- package/dist/src/core/monitoring/logger.js.map +1 -1
- package/dist/src/core/monitoring/metrics.d.ts +3 -0
- package/dist/src/core/monitoring/metrics.d.ts.map +1 -1
- package/dist/src/core/monitoring/metrics.js +142 -3
- package/dist/src/core/monitoring/metrics.js.map +1 -1
- package/dist/src/core/performance/context-cache.d.ts +109 -0
- package/dist/src/core/performance/context-cache.d.ts.map +1 -0
- package/dist/src/core/performance/context-cache.js +280 -0
- package/dist/src/core/performance/context-cache.js.map +1 -0
- package/dist/src/core/performance/index.d.ts +3 -0
- package/dist/src/core/performance/index.d.ts.map +1 -0
- package/dist/src/core/performance/index.js +3 -0
- package/dist/src/core/performance/index.js.map +1 -0
- package/dist/src/core/performance/lazy-context-loader.d.ts +93 -0
- package/dist/src/core/performance/lazy-context-loader.d.ts.map +1 -0
- package/dist/src/core/performance/lazy-context-loader.js +332 -0
- package/dist/src/core/performance/lazy-context-loader.js.map +1 -0
- package/dist/src/core/performance/monitor.d.ts +48 -0
- package/dist/src/core/performance/monitor.d.ts.map +1 -0
- package/dist/src/core/performance/monitor.js +226 -0
- package/dist/src/core/performance/monitor.js.map +1 -0
- package/dist/src/core/performance/optimized-frame-context.d.ts +74 -0
- package/dist/src/core/performance/optimized-frame-context.d.ts.map +1 -0
- package/dist/src/core/performance/optimized-frame-context.js +330 -0
- package/dist/src/core/performance/optimized-frame-context.js.map +1 -0
- package/dist/src/core/performance/performance-benchmark.d.ts +50 -0
- package/dist/src/core/performance/performance-benchmark.d.ts.map +1 -0
- package/dist/src/core/performance/performance-benchmark.js +290 -0
- package/dist/src/core/performance/performance-benchmark.js.map +1 -0
- package/dist/src/core/performance/performance-profiler.d.ts +151 -0
- package/dist/src/core/performance/performance-profiler.d.ts.map +1 -0
- package/dist/src/core/performance/performance-profiler.js +346 -0
- package/dist/src/core/performance/performance-profiler.js.map +1 -0
- package/dist/src/core/performance/streaming-jsonl-parser.d.ts +41 -0
- package/dist/src/core/performance/streaming-jsonl-parser.d.ts.map +1 -0
- package/dist/src/core/performance/streaming-jsonl-parser.js +193 -0
- package/dist/src/core/performance/streaming-jsonl-parser.js.map +1 -0
- package/dist/src/core/persistence/postgres-adapter.d.ts +31 -0
- package/dist/src/core/persistence/postgres-adapter.d.ts.map +1 -0
- package/dist/src/core/persistence/postgres-adapter.js +330 -0
- package/dist/src/core/persistence/postgres-adapter.js.map +1 -0
- package/dist/src/core/query/query-parser.d.ts +5 -0
- package/dist/src/core/query/query-parser.d.ts.map +1 -1
- package/dist/src/core/query/query-parser.js +86 -18
- package/dist/src/core/query/query-parser.js.map +1 -1
- package/dist/src/core/query/query-templates.d.ts +44 -0
- package/dist/src/core/query/query-templates.d.ts.map +1 -0
- package/dist/src/core/query/query-templates.js +326 -0
- package/dist/src/core/query/query-templates.js.map +1 -0
- package/dist/src/core/retrieval/llm-context-retrieval.d.ts +5 -3
- package/dist/src/core/retrieval/llm-context-retrieval.d.ts.map +1 -1
- package/dist/src/core/retrieval/llm-context-retrieval.js +73 -21
- package/dist/src/core/retrieval/llm-context-retrieval.js.map +1 -1
- package/dist/src/core/trace/cli-trace-wrapper.d.ts +23 -0
- package/dist/src/core/trace/cli-trace-wrapper.d.ts.map +1 -0
- package/dist/src/core/trace/cli-trace-wrapper.js +141 -0
- package/dist/src/core/trace/cli-trace-wrapper.js.map +1 -0
- package/dist/src/core/trace/db-trace-wrapper.d.ts +36 -0
- package/dist/src/core/trace/db-trace-wrapper.d.ts.map +1 -0
- package/dist/src/core/trace/db-trace-wrapper.js +252 -0
- package/dist/src/core/trace/db-trace-wrapper.js.map +1 -0
- package/dist/src/core/trace/debug-trace.d.ts +84 -0
- package/dist/src/core/trace/debug-trace.d.ts.map +1 -0
- package/dist/src/core/trace/debug-trace.js +402 -0
- package/dist/src/core/trace/debug-trace.js.map +1 -0
- package/dist/src/core/trace/error-test.d.ts +6 -0
- package/dist/src/core/trace/error-test.d.ts.map +1 -0
- package/dist/src/core/trace/error-test.js +128 -0
- package/dist/src/core/trace/error-test.js.map +1 -0
- package/dist/src/core/trace/index.d.ts +25 -0
- package/dist/src/core/trace/index.d.ts.map +1 -0
- package/dist/src/core/trace/index.js +121 -0
- package/dist/src/core/trace/index.js.map +1 -0
- package/dist/src/core/trace/linear-api-wrapper.d.ts +17 -0
- package/dist/src/core/trace/linear-api-wrapper.d.ts.map +1 -0
- package/dist/src/core/trace/linear-api-wrapper.js +205 -0
- package/dist/src/core/trace/linear-api-wrapper.js.map +1 -0
- package/dist/src/core/trace/performance-test.d.ts +6 -0
- package/dist/src/core/trace/performance-test.d.ts.map +1 -0
- package/dist/src/core/trace/performance-test.js +111 -0
- package/dist/src/core/trace/performance-test.js.map +1 -0
- package/dist/src/core/trace/trace-demo.d.ts +8 -0
- package/dist/src/core/trace/trace-demo.d.ts.map +1 -0
- package/dist/src/core/trace/trace-demo.js +154 -0
- package/dist/src/core/trace/trace-demo.js.map +1 -0
- package/dist/src/core/trace/trace-detector.d.ts +2 -2
- package/dist/src/core/trace/trace-detector.d.ts.map +1 -1
- package/dist/src/core/trace/trace-detector.demo.js +6 -6
- package/dist/src/core/trace/trace-detector.demo.js.map +1 -1
- package/dist/src/core/trace/trace-detector.js +3 -3
- package/dist/src/core/trace/trace-detector.js.map +1 -1
- package/dist/src/core/types.d.ts +35 -0
- package/dist/src/core/types.d.ts.map +1 -0
- package/dist/src/core/types.js +2 -0
- package/dist/src/core/types.js.map +1 -0
- package/dist/src/features/tasks/pebbles-task-store.d.ts +9 -2
- package/dist/src/features/tasks/pebbles-task-store.d.ts.map +1 -1
- package/dist/src/features/tasks/pebbles-task-store.js +97 -18
- package/dist/src/features/tasks/pebbles-task-store.js.map +1 -1
- package/dist/src/integrations/linear/auth.d.ts.map +1 -1
- package/dist/src/integrations/linear/auth.js.map +1 -1
- package/dist/src/integrations/linear/client.d.ts +15 -1
- package/dist/src/integrations/linear/client.d.ts.map +1 -1
- package/dist/src/integrations/linear/client.js +85 -3
- package/dist/src/integrations/linear/client.js.map +1 -1
- package/dist/src/integrations/linear/sync-manager.d.ts +2 -0
- package/dist/src/integrations/linear/sync-manager.d.ts.map +1 -1
- package/dist/src/integrations/linear/sync-manager.js +16 -4
- package/dist/src/integrations/linear/sync-manager.js.map +1 -1
- package/dist/src/integrations/linear/sync-service.d.ts +23 -2
- package/dist/src/integrations/linear/sync-service.d.ts.map +1 -1
- package/dist/src/integrations/linear/sync-service.js +44 -25
- package/dist/src/integrations/linear/sync-service.js.map +1 -1
- package/dist/src/integrations/linear/sync.d.ts +6 -0
- package/dist/src/integrations/linear/sync.d.ts.map +1 -1
- package/dist/src/integrations/linear/sync.js +27 -2
- package/dist/src/integrations/linear/sync.js.map +1 -1
- package/dist/src/integrations/linear/types.d.ts +16 -1
- package/dist/src/integrations/linear/types.d.ts.map +1 -1
- package/dist/src/integrations/linear/webhook-server.d.ts.map +1 -1
- package/dist/src/integrations/linear/webhook-server.js +10 -8
- package/dist/src/integrations/linear/webhook-server.js.map +1 -1
- package/dist/src/integrations/linear/webhook.d.ts +13 -0
- package/dist/src/integrations/linear/webhook.d.ts.map +1 -1
- package/dist/src/integrations/linear/webhook.js +101 -14
- package/dist/src/integrations/linear/webhook.js.map +1 -1
- package/dist/src/integrations/mcp/handlers/context-handlers.d.ts +39 -0
- package/dist/src/integrations/mcp/handlers/context-handlers.d.ts.map +1 -0
- package/dist/src/integrations/mcp/handlers/context-handlers.js +266 -0
- package/dist/src/integrations/mcp/handlers/context-handlers.js.map +1 -0
- package/dist/src/integrations/mcp/handlers/index.d.ts +37 -0
- package/dist/src/integrations/mcp/handlers/index.d.ts.map +1 -0
- package/dist/src/integrations/mcp/handlers/index.js +134 -0
- package/dist/src/integrations/mcp/handlers/index.js.map +1 -0
- package/dist/src/integrations/mcp/handlers/linear-handlers.d.ts +33 -0
- package/dist/src/integrations/mcp/handlers/linear-handlers.d.ts.map +1 -0
- package/dist/src/integrations/mcp/handlers/linear-handlers.js +251 -0
- package/dist/src/integrations/mcp/handlers/linear-handlers.js.map +1 -0
- package/dist/src/integrations/mcp/handlers/task-handlers.d.ts +42 -0
- package/dist/src/integrations/mcp/handlers/task-handlers.d.ts.map +1 -0
- package/dist/src/integrations/mcp/handlers/task-handlers.js +238 -0
- package/dist/src/integrations/mcp/handlers/task-handlers.js.map +1 -0
- package/dist/src/integrations/mcp/handlers/trace-handlers.d.ts +41 -0
- package/dist/src/integrations/mcp/handlers/trace-handlers.d.ts.map +1 -0
- package/dist/src/integrations/mcp/handlers/trace-handlers.js +298 -0
- package/dist/src/integrations/mcp/handlers/trace-handlers.js.map +1 -0
- package/dist/src/integrations/mcp/index.d.ts +13 -0
- package/dist/src/integrations/mcp/index.d.ts.map +1 -0
- package/dist/src/integrations/mcp/index.js +17 -0
- package/dist/src/integrations/mcp/index.js.map +1 -0
- package/dist/src/integrations/mcp/refactored-server.d.ts +76 -0
- package/dist/src/integrations/mcp/refactored-server.d.ts.map +1 -0
- package/dist/src/integrations/mcp/refactored-server.js +351 -0
- package/dist/src/integrations/mcp/refactored-server.js.map +1 -0
- package/dist/src/integrations/mcp/server.js +2 -2
- package/dist/src/integrations/mcp/server.js.map +1 -1
- package/dist/src/integrations/mcp/tool-definitions.d.ts +44 -0
- package/dist/src/integrations/mcp/tool-definitions.d.ts.map +1 -0
- package/dist/src/integrations/mcp/tool-definitions.js +563 -0
- package/dist/src/integrations/mcp/tool-definitions.js.map +1 -0
- package/dist/src/integrations/pg-aiguide/embedding-provider.d.ts +48 -0
- package/dist/src/integrations/pg-aiguide/embedding-provider.d.ts.map +1 -0
- package/dist/src/integrations/pg-aiguide/embedding-provider.js +190 -0
- package/dist/src/integrations/pg-aiguide/embedding-provider.js.map +1 -0
- package/dist/src/integrations/pg-aiguide/semantic-search.d.ts +34 -0
- package/dist/src/integrations/pg-aiguide/semantic-search.d.ts.map +1 -0
- package/dist/src/integrations/pg-aiguide/semantic-search.js +176 -0
- package/dist/src/integrations/pg-aiguide/semantic-search.js.map +1 -0
- package/dist/src/integrations/pg-aiguide/timescale-analytics.d.ts +44 -0
- package/dist/src/integrations/pg-aiguide/timescale-analytics.d.ts.map +1 -0
- package/dist/src/integrations/pg-aiguide/timescale-analytics.js +215 -0
- package/dist/src/integrations/pg-aiguide/timescale-analytics.js.map +1 -0
- package/dist/src/mcp/stackmemory-mcp-server.d.ts +9 -0
- package/dist/src/mcp/stackmemory-mcp-server.d.ts.map +1 -0
- package/dist/src/mcp/stackmemory-mcp-server.js +519 -0
- package/dist/src/mcp/stackmemory-mcp-server.js.map +1 -0
- package/dist/src/middleware/exponential-rate-limiter.d.ts +78 -0
- package/dist/src/middleware/exponential-rate-limiter.d.ts.map +1 -0
- package/dist/src/middleware/exponential-rate-limiter.js +293 -0
- package/dist/src/middleware/exponential-rate-limiter.js.map +1 -0
- package/dist/src/models/user.model.d.ts +62 -0
- package/dist/src/models/user.model.d.ts.map +1 -0
- package/dist/src/models/user.model.js +311 -0
- package/dist/src/models/user.model.js.map +1 -0
- package/dist/src/servers/production/auth-middleware.d.ts +12 -2
- package/dist/src/servers/production/auth-middleware.d.ts.map +1 -1
- package/dist/src/servers/production/auth-middleware.js +240 -28
- package/dist/src/servers/production/auth-middleware.js.map +1 -1
- package/dist/src/servers/railway/index.js.map +1 -1
- package/dist/src/services/context-service.d.ts.map +1 -1
- package/dist/src/services/context-service.js +86 -1
- package/dist/src/services/context-service.js.map +1 -1
- package/dist/src/validation/schemas.d.ts +633 -0
- package/dist/src/validation/schemas.d.ts.map +1 -0
- package/dist/src/validation/schemas.js +347 -0
- package/dist/src/validation/schemas.js.map +1 -0
- package/dist/types/task.js +1 -0
- package/dist/types/task.js.map +7 -0
- package/dist/utils/logger.js +52 -0
- package/dist/utils/logger.js.map +7 -0
- package/dist/validation/schemas.js +218 -0
- package/dist/validation/schemas.js.map +7 -0
- package/package.json +12 -3
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
import { logger } from "../monitoring/logger.js";
|
|
2
|
+
import { trace } from "../trace/index.js";
|
|
3
|
+
class BatchOperationsManager {
|
|
4
|
+
db;
|
|
5
|
+
preparedStatements = /* @__PURE__ */ new Map();
|
|
6
|
+
batchQueue = [];
|
|
7
|
+
isProcessing = false;
|
|
8
|
+
constructor(db) {
|
|
9
|
+
if (db) {
|
|
10
|
+
this.db = db;
|
|
11
|
+
this.initializePreparedStatements();
|
|
12
|
+
} else {
|
|
13
|
+
this.db = void 0;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Add events in bulk with optimized batching
|
|
18
|
+
*/
|
|
19
|
+
async bulkInsertEvents(events, options = {}) {
|
|
20
|
+
const {
|
|
21
|
+
batchSize = 100,
|
|
22
|
+
onConflict = "ignore",
|
|
23
|
+
enableTransactions = true
|
|
24
|
+
} = options;
|
|
25
|
+
return this.performBulkInsert("events", events, {
|
|
26
|
+
batchSize,
|
|
27
|
+
onConflict,
|
|
28
|
+
enableTransactions,
|
|
29
|
+
preprocessor: (event) => ({
|
|
30
|
+
...event,
|
|
31
|
+
event_id: `evt_${event.frame_id}_${event.seq}_${Date.now()}`,
|
|
32
|
+
payload: JSON.stringify(event.payload)
|
|
33
|
+
})
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Add anchors in bulk
|
|
38
|
+
*/
|
|
39
|
+
async bulkInsertAnchors(anchors, options = {}) {
|
|
40
|
+
return this.performBulkInsert("anchors", anchors, {
|
|
41
|
+
...options,
|
|
42
|
+
preprocessor: (anchor) => ({
|
|
43
|
+
...anchor,
|
|
44
|
+
anchor_id: `anc_${anchor.frame_id}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
|
|
45
|
+
metadata: JSON.stringify(anchor.metadata),
|
|
46
|
+
created_at: Date.now()
|
|
47
|
+
})
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Bulk update frame digests
|
|
52
|
+
*/
|
|
53
|
+
async bulkUpdateFrameDigests(updates, options = {}) {
|
|
54
|
+
const {
|
|
55
|
+
batchSize = 50,
|
|
56
|
+
enableTransactions = true
|
|
57
|
+
} = options;
|
|
58
|
+
return trace.traceAsync("function", "bulkUpdateFrameDigests", { count: updates.length }, async () => {
|
|
59
|
+
const startTime = performance.now();
|
|
60
|
+
const stats = {
|
|
61
|
+
totalRecords: updates.length,
|
|
62
|
+
batchesProcessed: 0,
|
|
63
|
+
successfulInserts: 0,
|
|
64
|
+
failedInserts: 0,
|
|
65
|
+
totalTimeMs: 0,
|
|
66
|
+
avgBatchTimeMs: 0
|
|
67
|
+
};
|
|
68
|
+
if (updates.length === 0) return stats;
|
|
69
|
+
const stmt = this.db.prepare(`
|
|
70
|
+
UPDATE frames
|
|
71
|
+
SET digest_text = ?,
|
|
72
|
+
digest_json = ?,
|
|
73
|
+
closed_at = COALESCE(?, closed_at),
|
|
74
|
+
state = CASE WHEN ? IS NOT NULL THEN 'closed' ELSE state END
|
|
75
|
+
WHERE frame_id = ?
|
|
76
|
+
`);
|
|
77
|
+
const updateFn = (batch) => {
|
|
78
|
+
for (const update of batch) {
|
|
79
|
+
try {
|
|
80
|
+
const result = stmt.run(
|
|
81
|
+
update.digest_text,
|
|
82
|
+
JSON.stringify(update.digest_json),
|
|
83
|
+
update.closed_at,
|
|
84
|
+
update.closed_at,
|
|
85
|
+
update.frame_id
|
|
86
|
+
);
|
|
87
|
+
stats.successfulInserts += result.changes;
|
|
88
|
+
} catch (error) {
|
|
89
|
+
stats.failedInserts++;
|
|
90
|
+
logger.warn("Failed to update frame digest", {
|
|
91
|
+
frameId: update.frame_id,
|
|
92
|
+
error: error.message
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
if (enableTransactions) {
|
|
98
|
+
const transaction = this.db.transaction(updateFn);
|
|
99
|
+
await this.processBatches(updates, batchSize, transaction, stats);
|
|
100
|
+
} else {
|
|
101
|
+
await this.processBatches(updates, batchSize, updateFn, stats);
|
|
102
|
+
}
|
|
103
|
+
stats.totalTimeMs = performance.now() - startTime;
|
|
104
|
+
stats.avgBatchTimeMs = stats.batchesProcessed > 0 ? stats.totalTimeMs / stats.batchesProcessed : 0;
|
|
105
|
+
logger.info("Bulk frame digest update completed", stats);
|
|
106
|
+
return stats;
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Generic bulk insert with preprocessing
|
|
111
|
+
*/
|
|
112
|
+
async performBulkInsert(table, records, options = {}) {
|
|
113
|
+
const {
|
|
114
|
+
batchSize = 100,
|
|
115
|
+
onConflict = "ignore",
|
|
116
|
+
enableTransactions = true,
|
|
117
|
+
preprocessor
|
|
118
|
+
} = options;
|
|
119
|
+
return trace.traceAsync("function", `bulkInsert${table}`, { count: records.length }, async () => {
|
|
120
|
+
const startTime = performance.now();
|
|
121
|
+
const stats = {
|
|
122
|
+
totalRecords: records.length,
|
|
123
|
+
batchesProcessed: 0,
|
|
124
|
+
successfulInserts: 0,
|
|
125
|
+
failedInserts: 0,
|
|
126
|
+
totalTimeMs: 0,
|
|
127
|
+
avgBatchTimeMs: 0
|
|
128
|
+
};
|
|
129
|
+
if (records.length === 0) return stats;
|
|
130
|
+
const processedRecords = preprocessor ? records.map(preprocessor) : records;
|
|
131
|
+
const firstRecord = processedRecords[0];
|
|
132
|
+
const columns = Object.keys(firstRecord);
|
|
133
|
+
const placeholders = columns.map(() => "?").join(", ");
|
|
134
|
+
const conflictClause = this.getConflictClause(onConflict);
|
|
135
|
+
const insertSql = `INSERT ${conflictClause} INTO ${table} (${columns.join(", ")}) VALUES (${placeholders})`;
|
|
136
|
+
const stmt = this.db.prepare(insertSql);
|
|
137
|
+
const insertFn = (batch) => {
|
|
138
|
+
for (const record of batch) {
|
|
139
|
+
try {
|
|
140
|
+
const values = columns.map((col) => record[col]);
|
|
141
|
+
const result = stmt.run(...values);
|
|
142
|
+
stats.successfulInserts += result.changes;
|
|
143
|
+
} catch (error) {
|
|
144
|
+
stats.failedInserts++;
|
|
145
|
+
logger.warn(`Failed to insert ${table} record`, {
|
|
146
|
+
record,
|
|
147
|
+
error: error.message
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
if (enableTransactions) {
|
|
153
|
+
const transaction = this.db.transaction(insertFn);
|
|
154
|
+
await this.processBatches(processedRecords, batchSize, transaction, stats);
|
|
155
|
+
} else {
|
|
156
|
+
await this.processBatches(processedRecords, batchSize, insertFn, stats);
|
|
157
|
+
}
|
|
158
|
+
stats.totalTimeMs = performance.now() - startTime;
|
|
159
|
+
stats.avgBatchTimeMs = stats.batchesProcessed > 0 ? stats.totalTimeMs / stats.batchesProcessed : 0;
|
|
160
|
+
logger.info(`Bulk ${table} insert completed`, stats);
|
|
161
|
+
return stats;
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Process records in batches
|
|
166
|
+
*/
|
|
167
|
+
async processBatches(records, batchSize, processFn, stats) {
|
|
168
|
+
for (let i = 0; i < records.length; i += batchSize) {
|
|
169
|
+
const batch = records.slice(i, i + batchSize);
|
|
170
|
+
const batchStart = performance.now();
|
|
171
|
+
try {
|
|
172
|
+
processFn(batch);
|
|
173
|
+
stats.batchesProcessed++;
|
|
174
|
+
const batchTime = performance.now() - batchStart;
|
|
175
|
+
logger.debug("Batch processed", {
|
|
176
|
+
batchNumber: stats.batchesProcessed,
|
|
177
|
+
records: batch.length,
|
|
178
|
+
timeMs: batchTime.toFixed(2)
|
|
179
|
+
});
|
|
180
|
+
if (stats.batchesProcessed % 10 === 0) {
|
|
181
|
+
await new Promise((resolve) => setImmediate(resolve));
|
|
182
|
+
}
|
|
183
|
+
} catch (error) {
|
|
184
|
+
stats.failedInserts += batch.length;
|
|
185
|
+
logger.error("Batch processing failed", error, {
|
|
186
|
+
batchNumber: stats.batchesProcessed + 1,
|
|
187
|
+
batchSize: batch.length
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Queue batch operation for later processing
|
|
194
|
+
*/
|
|
195
|
+
queueBatchOperation(operation) {
|
|
196
|
+
this.batchQueue.push(operation);
|
|
197
|
+
if (this.batchQueue.length >= 10 && !this.isProcessing) {
|
|
198
|
+
setImmediate(() => this.processBatchQueue());
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Process queued batch operations
|
|
203
|
+
*/
|
|
204
|
+
async processBatchQueue() {
|
|
205
|
+
if (this.isProcessing || this.batchQueue.length === 0) {
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
this.isProcessing = true;
|
|
209
|
+
const operations = [...this.batchQueue];
|
|
210
|
+
this.batchQueue = [];
|
|
211
|
+
try {
|
|
212
|
+
const groupedOps = this.groupOperationsByTable(operations);
|
|
213
|
+
for (const [table, tableOps] of groupedOps) {
|
|
214
|
+
await this.processTableOperations(table, tableOps);
|
|
215
|
+
}
|
|
216
|
+
logger.info("Batch queue processed", {
|
|
217
|
+
operations: operations.length,
|
|
218
|
+
tables: groupedOps.size
|
|
219
|
+
});
|
|
220
|
+
} catch (error) {
|
|
221
|
+
logger.error("Batch queue processing failed", error);
|
|
222
|
+
} finally {
|
|
223
|
+
this.isProcessing = false;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Flush any remaining queued operations
|
|
228
|
+
*/
|
|
229
|
+
async flush() {
|
|
230
|
+
if (this.batchQueue.length > 0) {
|
|
231
|
+
await this.processBatchQueue();
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Get SQL conflict clause
|
|
236
|
+
*/
|
|
237
|
+
getConflictClause(onConflict) {
|
|
238
|
+
switch (onConflict) {
|
|
239
|
+
case "ignore":
|
|
240
|
+
return "OR IGNORE";
|
|
241
|
+
case "replace":
|
|
242
|
+
return "OR REPLACE";
|
|
243
|
+
case "update":
|
|
244
|
+
return "ON CONFLICT DO UPDATE SET";
|
|
245
|
+
default:
|
|
246
|
+
return "";
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Group operations by table for efficient processing
|
|
251
|
+
*/
|
|
252
|
+
groupOperationsByTable(operations) {
|
|
253
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
254
|
+
for (const op of operations) {
|
|
255
|
+
if (!grouped.has(op.table)) {
|
|
256
|
+
grouped.set(op.table, []);
|
|
257
|
+
}
|
|
258
|
+
grouped.get(op.table).push(op);
|
|
259
|
+
}
|
|
260
|
+
return grouped;
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Process all operations for a specific table
|
|
264
|
+
*/
|
|
265
|
+
async processTableOperations(table, operations) {
|
|
266
|
+
for (const op of operations) {
|
|
267
|
+
switch (op.operation) {
|
|
268
|
+
case "insert":
|
|
269
|
+
await this.performBulkInsert(table, op.data, {
|
|
270
|
+
onConflict: op.onConflict
|
|
271
|
+
});
|
|
272
|
+
break;
|
|
273
|
+
// Add update and delete operations as needed
|
|
274
|
+
default:
|
|
275
|
+
logger.warn("Unsupported batch operation", { table, operation: op.operation });
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Initialize commonly used prepared statements
|
|
281
|
+
*/
|
|
282
|
+
initializePreparedStatements() {
|
|
283
|
+
this.preparedStatements.set(
|
|
284
|
+
"insert_event",
|
|
285
|
+
this.db.prepare(`
|
|
286
|
+
INSERT OR IGNORE INTO events
|
|
287
|
+
(event_id, frame_id, run_id, seq, event_type, payload, ts)
|
|
288
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
289
|
+
`)
|
|
290
|
+
);
|
|
291
|
+
this.preparedStatements.set(
|
|
292
|
+
"insert_anchor",
|
|
293
|
+
this.db.prepare(`
|
|
294
|
+
INSERT OR IGNORE INTO anchors
|
|
295
|
+
(anchor_id, frame_id, type, text, priority, metadata, created_at)
|
|
296
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
297
|
+
`)
|
|
298
|
+
);
|
|
299
|
+
logger.info("Batch operations prepared statements initialized");
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Cleanup resources
|
|
303
|
+
*/
|
|
304
|
+
cleanup() {
|
|
305
|
+
this.preparedStatements.clear();
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
let globalBatchManager = null;
|
|
309
|
+
function getBatchManager(db) {
|
|
310
|
+
if (!globalBatchManager) {
|
|
311
|
+
globalBatchManager = new BatchOperationsManager(db);
|
|
312
|
+
}
|
|
313
|
+
return globalBatchManager;
|
|
314
|
+
}
|
|
315
|
+
async function bulkInsertEvents(events, options) {
|
|
316
|
+
const manager = getBatchManager();
|
|
317
|
+
return manager.bulkInsertEvents(events, options);
|
|
318
|
+
}
|
|
319
|
+
async function bulkInsertAnchors(anchors, options) {
|
|
320
|
+
const manager = getBatchManager();
|
|
321
|
+
return manager.bulkInsertAnchors(anchors, options);
|
|
322
|
+
}
|
|
323
|
+
export {
|
|
324
|
+
BatchOperationsManager,
|
|
325
|
+
bulkInsertAnchors,
|
|
326
|
+
bulkInsertEvents,
|
|
327
|
+
getBatchManager
|
|
328
|
+
};
|
|
329
|
+
//# sourceMappingURL=batch-operations.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/core/database/batch-operations.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Batch Database Operations\n * High-performance bulk operations with transaction management\n */\n\nimport Database from 'better-sqlite3';\nimport { getConnectionPool } from './connection-pool.js';\nimport { logger } from '../monitoring/logger.js';\nimport { trace } from '../trace/index.js';\n\nexport interface BatchOperation {\n table: string;\n operation: 'insert' | 'update' | 'delete';\n data: Record<string, any>[];\n onConflict?: 'ignore' | 'replace' | 'update';\n}\n\nexport interface BulkInsertOptions {\n batchSize?: number;\n onConflict?: 'ignore' | 'replace' | 'update';\n enableTransactions?: boolean;\n parallelTables?: boolean;\n}\n\nexport interface BatchStats {\n totalRecords: number;\n batchesProcessed: number;\n successfulInserts: number;\n failedInserts: number;\n totalTimeMs: number;\n avgBatchTimeMs: number;\n}\n\n/**\n * High-performance batch operations manager\n */\nexport class BatchOperationsManager {\n private db: Database.Database;\n private preparedStatements = new Map<string, Database.Statement>();\n private batchQueue: BatchOperation[] = [];\n private isProcessing = false;\n\n constructor(db?: Database.Database) {\n if (db) {\n this.db = db;\n this.initializePreparedStatements();\n } else {\n // Will be initialized when used with getConnectionPool().withConnection()\n this.db = undefined as any;\n }\n }\n\n /**\n * Add events in bulk with optimized batching\n */\n async bulkInsertEvents(\n events: Array<{\n frame_id: string;\n run_id: string;\n seq: number;\n event_type: string;\n payload: any;\n ts: number;\n }>,\n options: BulkInsertOptions = {}\n ): Promise<BatchStats> {\n const {\n batchSize = 100,\n onConflict = 'ignore',\n enableTransactions = true,\n } = options;\n\n return this.performBulkInsert('events', events, {\n batchSize,\n onConflict,\n enableTransactions,\n preprocessor: (event) => ({\n ...event,\n event_id: `evt_${event.frame_id}_${event.seq}_${Date.now()}`,\n payload: JSON.stringify(event.payload),\n }),\n });\n }\n\n /**\n * Add anchors in bulk\n */\n async bulkInsertAnchors(\n anchors: Array<{\n frame_id: string;\n type: string;\n text: string;\n priority: number;\n metadata: any;\n }>,\n options: BulkInsertOptions = {}\n ): Promise<BatchStats> {\n return this.performBulkInsert('anchors', anchors, {\n ...options,\n preprocessor: (anchor) => ({\n ...anchor,\n anchor_id: `anc_${anchor.frame_id}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,\n metadata: JSON.stringify(anchor.metadata),\n created_at: Date.now(),\n }),\n });\n }\n\n /**\n * Bulk update frame digests\n */\n async bulkUpdateFrameDigests(\n updates: Array<{\n frame_id: string;\n digest_text: string;\n digest_json: any;\n closed_at?: number;\n }>,\n options: BulkInsertOptions = {}\n ): Promise<BatchStats> {\n const {\n batchSize = 50,\n enableTransactions = true,\n } = options;\n\n return trace.traceAsync('function', 'bulkUpdateFrameDigests', { count: updates.length }, async () => {\n const startTime = performance.now();\n const stats: BatchStats = {\n totalRecords: updates.length,\n batchesProcessed: 0,\n successfulInserts: 0,\n failedInserts: 0,\n totalTimeMs: 0,\n avgBatchTimeMs: 0,\n };\n\n if (updates.length === 0) return stats;\n\n const stmt = this.db.prepare(`\n UPDATE frames \n SET digest_text = ?, \n digest_json = ?, \n closed_at = COALESCE(?, closed_at),\n state = CASE WHEN ? IS NOT NULL THEN 'closed' ELSE state END\n WHERE frame_id = ?\n `);\n\n const updateFn = (batch: typeof updates) => {\n for (const update of batch) {\n try {\n const result = stmt.run(\n update.digest_text,\n JSON.stringify(update.digest_json),\n update.closed_at,\n update.closed_at,\n update.frame_id\n );\n stats.successfulInserts += result.changes;\n } catch (error) {\n stats.failedInserts++;\n logger.warn('Failed to update frame digest', {\n frameId: update.frame_id,\n error: (error as Error).message,\n });\n }\n }\n };\n\n if (enableTransactions) {\n const transaction = this.db.transaction(updateFn);\n await this.processBatches(updates, batchSize, transaction, stats);\n } else {\n await this.processBatches(updates, batchSize, updateFn, stats);\n }\n\n stats.totalTimeMs = performance.now() - startTime;\n stats.avgBatchTimeMs = stats.batchesProcessed > 0 \n ? stats.totalTimeMs / stats.batchesProcessed \n : 0;\n\n logger.info('Bulk frame digest update completed', stats as unknown as Record<string, unknown>);\n return stats;\n });\n }\n\n /**\n * Generic bulk insert with preprocessing\n */\n private async performBulkInsert<T extends Record<string, any>>(\n table: string,\n records: T[],\n options: BulkInsertOptions & {\n preprocessor?: (record: T) => Record<string, any>;\n } = {}\n ): Promise<BatchStats> {\n const {\n batchSize = 100,\n onConflict = 'ignore',\n enableTransactions = true,\n preprocessor,\n } = options;\n\n return trace.traceAsync('function', `bulkInsert${table}`, { count: records.length }, async () => {\n const startTime = performance.now();\n const stats: BatchStats = {\n totalRecords: records.length,\n batchesProcessed: 0,\n successfulInserts: 0,\n failedInserts: 0,\n totalTimeMs: 0,\n avgBatchTimeMs: 0,\n };\n\n if (records.length === 0) return stats;\n\n // Preprocess records if needed\n const processedRecords = preprocessor \n ? records.map(preprocessor)\n : records;\n\n // Build dynamic insert statement\n const firstRecord = processedRecords[0];\n const columns = Object.keys(firstRecord);\n const placeholders = columns.map(() => '?').join(', ');\n const conflictClause = this.getConflictClause(onConflict);\n \n const insertSql = `INSERT ${conflictClause} INTO ${table} (${columns.join(', ')}) VALUES (${placeholders})`;\n const stmt = this.db.prepare(insertSql);\n\n const insertFn = (batch: typeof processedRecords) => {\n for (const record of batch) {\n try {\n const values = columns.map(col => record[col]);\n const result = stmt.run(...values);\n stats.successfulInserts += result.changes;\n } catch (error) {\n stats.failedInserts++;\n logger.warn(`Failed to insert ${table} record`, {\n record,\n error: (error as Error).message,\n });\n }\n }\n };\n\n if (enableTransactions) {\n const transaction = this.db.transaction(insertFn);\n await this.processBatches(processedRecords, batchSize, transaction, stats);\n } else {\n await this.processBatches(processedRecords, batchSize, insertFn, stats);\n }\n\n stats.totalTimeMs = performance.now() - startTime;\n stats.avgBatchTimeMs = stats.batchesProcessed > 0 \n ? stats.totalTimeMs / stats.batchesProcessed \n : 0;\n\n logger.info(`Bulk ${table} insert completed`, stats as unknown as Record<string, unknown>);\n return stats;\n });\n }\n\n /**\n * Process records in batches\n */\n private async processBatches<T>(\n records: T[],\n batchSize: number,\n processFn: (batch: T[]) => void,\n stats: BatchStats\n ): Promise<void> {\n for (let i = 0; i < records.length; i += batchSize) {\n const batch = records.slice(i, i + batchSize);\n const batchStart = performance.now();\n \n try {\n processFn(batch);\n stats.batchesProcessed++;\n \n const batchTime = performance.now() - batchStart;\n logger.debug('Batch processed', {\n batchNumber: stats.batchesProcessed,\n records: batch.length,\n timeMs: batchTime.toFixed(2),\n });\n\n // Yield control to prevent blocking\n if (stats.batchesProcessed % 10 === 0) {\n await new Promise(resolve => setImmediate(resolve));\n }\n\n } catch (error) {\n stats.failedInserts += batch.length;\n logger.error('Batch processing failed', error as Error, {\n batchNumber: stats.batchesProcessed + 1,\n batchSize: batch.length,\n });\n }\n }\n }\n\n /**\n * Queue batch operation for later processing\n */\n queueBatchOperation(operation: BatchOperation): void {\n this.batchQueue.push(operation);\n \n if (this.batchQueue.length >= 10 && !this.isProcessing) {\n setImmediate(() => this.processBatchQueue());\n }\n }\n\n /**\n * Process queued batch operations\n */\n async processBatchQueue(): Promise<void> {\n if (this.isProcessing || this.batchQueue.length === 0) {\n return;\n }\n\n this.isProcessing = true;\n const operations = [...this.batchQueue];\n this.batchQueue = [];\n\n try {\n const groupedOps = this.groupOperationsByTable(operations);\n \n for (const [table, tableOps] of groupedOps) {\n await this.processTableOperations(table, tableOps);\n }\n\n logger.info('Batch queue processed', {\n operations: operations.length,\n tables: groupedOps.size,\n });\n\n } catch (error) {\n logger.error('Batch queue processing failed', error as Error);\n } finally {\n this.isProcessing = false;\n }\n }\n\n /**\n * Flush any remaining queued operations\n */\n async flush(): Promise<void> {\n if (this.batchQueue.length > 0) {\n await this.processBatchQueue();\n }\n }\n\n /**\n * Get SQL conflict clause\n */\n private getConflictClause(onConflict: string): string {\n switch (onConflict) {\n case 'ignore':\n return 'OR IGNORE';\n case 'replace':\n return 'OR REPLACE';\n case 'update':\n return 'ON CONFLICT DO UPDATE SET';\n default:\n return '';\n }\n }\n\n /**\n * Group operations by table for efficient processing\n */\n private groupOperationsByTable(operations: BatchOperation[]): Map<string, BatchOperation[]> {\n const grouped = new Map<string, BatchOperation[]>();\n \n for (const op of operations) {\n if (!grouped.has(op.table)) {\n grouped.set(op.table, []);\n }\n grouped.get(op.table)!.push(op);\n }\n \n return grouped;\n }\n\n /**\n * Process all operations for a specific table\n */\n private async processTableOperations(table: string, operations: BatchOperation[]): Promise<void> {\n for (const op of operations) {\n switch (op.operation) {\n case 'insert':\n await this.performBulkInsert(table, op.data, {\n onConflict: op.onConflict,\n });\n break;\n // Add update and delete operations as needed\n default:\n logger.warn('Unsupported batch operation', { table, operation: op.operation });\n }\n }\n }\n\n /**\n * Initialize commonly used prepared statements\n */\n private initializePreparedStatements(): void {\n // Event insertion\n this.preparedStatements.set('insert_event', \n this.db.prepare(`\n INSERT OR IGNORE INTO events \n (event_id, frame_id, run_id, seq, event_type, payload, ts) \n VALUES (?, ?, ?, ?, ?, ?, ?)\n `)\n );\n\n // Anchor insertion\n this.preparedStatements.set('insert_anchor',\n this.db.prepare(`\n INSERT OR IGNORE INTO anchors \n (anchor_id, frame_id, type, text, priority, metadata, created_at) \n VALUES (?, ?, ?, ?, ?, ?, ?)\n `)\n );\n\n logger.info('Batch operations prepared statements initialized');\n }\n\n /**\n * Cleanup resources\n */\n cleanup(): void {\n // Modern better-sqlite3 automatically handles cleanup\n this.preparedStatements.clear();\n }\n}\n\n// Global batch operations manager\nlet globalBatchManager: BatchOperationsManager | null = null;\n\n/**\n * Get or create global batch operations manager\n */\nexport function getBatchManager(db?: Database.Database): BatchOperationsManager {\n if (!globalBatchManager) {\n globalBatchManager = new BatchOperationsManager(db);\n }\n return globalBatchManager;\n}\n\n/**\n * Convenience function for bulk event insertion\n */\nexport async function bulkInsertEvents(\n events: any[],\n options?: BulkInsertOptions\n): Promise<BatchStats> {\n const manager = getBatchManager();\n return manager.bulkInsertEvents(events, options);\n}\n\n/**\n * Convenience function for bulk anchor insertion\n */\nexport async function bulkInsertAnchors(\n anchors: any[],\n options?: BulkInsertOptions\n): Promise<BatchStats> {\n const manager = getBatchManager();\n return manager.bulkInsertAnchors(anchors, options);\n}"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import { createTracedDatabase } from "../trace/db-trace-wrapper.js";
|
|
2
|
+
import { logger } from "../monitoring/logger.js";
|
|
3
|
+
class SQLiteConnectionPool {
|
|
4
|
+
connections = /* @__PURE__ */ new Map();
|
|
5
|
+
filename;
|
|
6
|
+
options;
|
|
7
|
+
maxConnections;
|
|
8
|
+
acquireTimeoutMs;
|
|
9
|
+
idleTimeoutMs;
|
|
10
|
+
cleanupInterval = null;
|
|
11
|
+
// Statistics
|
|
12
|
+
stats = {
|
|
13
|
+
totalCreated: 0,
|
|
14
|
+
totalAcquired: 0,
|
|
15
|
+
totalReleased: 0,
|
|
16
|
+
currentActive: 0,
|
|
17
|
+
currentIdle: 0
|
|
18
|
+
};
|
|
19
|
+
constructor(filename, options = {}) {
|
|
20
|
+
this.filename = filename;
|
|
21
|
+
this.options = options;
|
|
22
|
+
this.maxConnections = options.maxConnections ?? 5;
|
|
23
|
+
this.acquireTimeoutMs = options.acquireTimeoutMs ?? 5e3;
|
|
24
|
+
this.idleTimeoutMs = options.idleTimeoutMs ?? 3e5;
|
|
25
|
+
if (options.checkInterval !== 0) {
|
|
26
|
+
this.cleanupInterval = setInterval(
|
|
27
|
+
() => this.cleanup(),
|
|
28
|
+
options.checkInterval ?? 6e4
|
|
29
|
+
// 1 minute
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
logger.info("SQLite connection pool initialized", {
|
|
33
|
+
filename,
|
|
34
|
+
maxConnections: this.maxConnections,
|
|
35
|
+
acquireTimeoutMs: this.acquireTimeoutMs,
|
|
36
|
+
idleTimeoutMs: this.idleTimeoutMs
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Acquire a connection from the pool
|
|
41
|
+
*/
|
|
42
|
+
async acquire() {
|
|
43
|
+
const startTime = Date.now();
|
|
44
|
+
while (Date.now() - startTime < this.acquireTimeoutMs) {
|
|
45
|
+
for (const [id, connection] of this.connections) {
|
|
46
|
+
if (!connection.inUse) {
|
|
47
|
+
connection.inUse = true;
|
|
48
|
+
connection.lastUsed = Date.now();
|
|
49
|
+
this.stats.totalAcquired++;
|
|
50
|
+
this.stats.currentActive++;
|
|
51
|
+
this.stats.currentIdle--;
|
|
52
|
+
logger.debug("Reused connection from pool", { connectionId: id });
|
|
53
|
+
return connection;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
if (this.connections.size < this.maxConnections) {
|
|
57
|
+
return this.createConnection();
|
|
58
|
+
}
|
|
59
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
60
|
+
}
|
|
61
|
+
throw new Error(`Failed to acquire connection within ${this.acquireTimeoutMs}ms timeout`);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Release a connection back to the pool
|
|
65
|
+
*/
|
|
66
|
+
release(connection) {
|
|
67
|
+
if (this.connections.has(connection.id)) {
|
|
68
|
+
connection.inUse = false;
|
|
69
|
+
connection.lastUsed = Date.now();
|
|
70
|
+
this.stats.totalReleased++;
|
|
71
|
+
this.stats.currentActive--;
|
|
72
|
+
this.stats.currentIdle++;
|
|
73
|
+
logger.debug("Released connection to pool", { connectionId: connection.id });
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Execute a function with a pooled connection
|
|
78
|
+
*/
|
|
79
|
+
async withConnection(fn) {
|
|
80
|
+
const connection = await this.acquire();
|
|
81
|
+
try {
|
|
82
|
+
return await fn(connection.db);
|
|
83
|
+
} finally {
|
|
84
|
+
this.release(connection);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Execute a transaction with a pooled connection
|
|
89
|
+
*/
|
|
90
|
+
async withTransaction(fn) {
|
|
91
|
+
const connection = await this.acquire();
|
|
92
|
+
try {
|
|
93
|
+
const transaction = connection.db.transaction(() => fn(connection.db));
|
|
94
|
+
return transaction();
|
|
95
|
+
} finally {
|
|
96
|
+
this.release(connection);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Get pool statistics
|
|
101
|
+
*/
|
|
102
|
+
getStats() {
|
|
103
|
+
return {
|
|
104
|
+
...this.stats,
|
|
105
|
+
totalConnections: this.connections.size,
|
|
106
|
+
maxConnections: this.maxConnections
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Close all connections and cleanup
|
|
111
|
+
*/
|
|
112
|
+
async close() {
|
|
113
|
+
if (this.cleanupInterval) {
|
|
114
|
+
clearInterval(this.cleanupInterval);
|
|
115
|
+
this.cleanupInterval = null;
|
|
116
|
+
}
|
|
117
|
+
for (const [id, connection] of this.connections) {
|
|
118
|
+
try {
|
|
119
|
+
connection.db.close();
|
|
120
|
+
logger.debug("Closed connection", { connectionId: id });
|
|
121
|
+
} catch (error) {
|
|
122
|
+
logger.warn("Error closing connection", {
|
|
123
|
+
connectionId: id,
|
|
124
|
+
error: error.message
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
this.connections.clear();
|
|
129
|
+
this.stats.currentActive = 0;
|
|
130
|
+
this.stats.currentIdle = 0;
|
|
131
|
+
logger.info("Connection pool closed", {
|
|
132
|
+
totalCreated: this.stats.totalCreated,
|
|
133
|
+
totalAcquired: this.stats.totalAcquired,
|
|
134
|
+
totalReleased: this.stats.totalReleased
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Create a new connection
|
|
139
|
+
*/
|
|
140
|
+
createConnection() {
|
|
141
|
+
const id = `conn_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
142
|
+
const now = Date.now();
|
|
143
|
+
const db = createTracedDatabase(this.filename, this.options);
|
|
144
|
+
db.pragma("journal_mode = WAL");
|
|
145
|
+
db.pragma("synchronous = NORMAL");
|
|
146
|
+
db.pragma("cache_size = 1000");
|
|
147
|
+
db.pragma("temp_store = MEMORY");
|
|
148
|
+
const connection = {
|
|
149
|
+
db,
|
|
150
|
+
id,
|
|
151
|
+
createdAt: now,
|
|
152
|
+
lastUsed: now,
|
|
153
|
+
inUse: true
|
|
154
|
+
};
|
|
155
|
+
this.connections.set(id, connection);
|
|
156
|
+
this.stats.totalCreated++;
|
|
157
|
+
this.stats.totalAcquired++;
|
|
158
|
+
this.stats.currentActive++;
|
|
159
|
+
logger.debug("Created new connection", {
|
|
160
|
+
connectionId: id,
|
|
161
|
+
totalConnections: this.connections.size
|
|
162
|
+
});
|
|
163
|
+
return connection;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Clean up idle connections
|
|
167
|
+
*/
|
|
168
|
+
cleanup() {
|
|
169
|
+
const now = Date.now();
|
|
170
|
+
const toRemove = [];
|
|
171
|
+
for (const [id, connection] of this.connections) {
|
|
172
|
+
if (!connection.inUse && now - connection.lastUsed > this.idleTimeoutMs) {
|
|
173
|
+
toRemove.push(id);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
for (const id of toRemove) {
|
|
177
|
+
const connection = this.connections.get(id);
|
|
178
|
+
if (connection) {
|
|
179
|
+
try {
|
|
180
|
+
connection.db.close();
|
|
181
|
+
this.connections.delete(id);
|
|
182
|
+
this.stats.currentIdle--;
|
|
183
|
+
logger.debug("Cleaned up idle connection", {
|
|
184
|
+
connectionId: id,
|
|
185
|
+
idleTime: now - connection.lastUsed
|
|
186
|
+
});
|
|
187
|
+
} catch (error) {
|
|
188
|
+
logger.warn("Error cleaning up connection", {
|
|
189
|
+
connectionId: id,
|
|
190
|
+
error: error.message
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
if (toRemove.length > 0) {
|
|
196
|
+
logger.info("Connection cleanup completed", {
|
|
197
|
+
removed: toRemove.length,
|
|
198
|
+
remaining: this.connections.size
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
let globalPool = null;
|
|
204
|
+
function getConnectionPool(filename, options) {
|
|
205
|
+
if (!globalPool && filename) {
|
|
206
|
+
globalPool = new SQLiteConnectionPool(filename, options);
|
|
207
|
+
}
|
|
208
|
+
if (!globalPool) {
|
|
209
|
+
throw new Error("Connection pool not initialized. Call with filename first.");
|
|
210
|
+
}
|
|
211
|
+
return globalPool;
|
|
212
|
+
}
|
|
213
|
+
async function closeGlobalPool() {
|
|
214
|
+
if (globalPool) {
|
|
215
|
+
await globalPool.close();
|
|
216
|
+
globalPool = null;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
export {
|
|
220
|
+
SQLiteConnectionPool,
|
|
221
|
+
closeGlobalPool,
|
|
222
|
+
getConnectionPool
|
|
223
|
+
};
|
|
224
|
+
//# sourceMappingURL=connection-pool.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/core/database/connection-pool.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * SQLite Connection Pool\n * Manages a pool of SQLite database connections for performance optimization\n */\n\nimport Database from 'better-sqlite3';\nimport { createTracedDatabase, TracedDatabaseOptions } from '../trace/db-trace-wrapper.js';\nimport { logger } from '../monitoring/logger.js';\n\nexport interface ConnectionPoolOptions extends TracedDatabaseOptions {\n maxConnections?: number;\n acquireTimeoutMs?: number;\n idleTimeoutMs?: number;\n checkInterval?: number;\n}\n\nexport interface PooledConnection {\n db: Database.Database;\n id: string;\n createdAt: number;\n lastUsed: number;\n inUse: boolean;\n}\n\nexport class SQLiteConnectionPool {\n private connections: Map<string, PooledConnection> = new Map();\n private filename: string;\n private options: ConnectionPoolOptions;\n private maxConnections: number;\n private acquireTimeoutMs: number;\n private idleTimeoutMs: number;\n private cleanupInterval: NodeJS.Timeout | null = null;\n \n // Statistics\n private stats = {\n totalCreated: 0,\n totalAcquired: 0,\n totalReleased: 0,\n currentActive: 0,\n currentIdle: 0,\n };\n\n constructor(filename: string, options: ConnectionPoolOptions = {}) {\n this.filename = filename;\n this.options = options;\n this.maxConnections = options.maxConnections ?? 5;\n this.acquireTimeoutMs = options.acquireTimeoutMs ?? 5000;\n this.idleTimeoutMs = options.idleTimeoutMs ?? 300000; // 5 minutes\n \n // Start cleanup interval\n if (options.checkInterval !== 0) {\n this.cleanupInterval = setInterval(\n () => this.cleanup(),\n options.checkInterval ?? 60000 // 1 minute\n );\n }\n\n logger.info('SQLite connection pool initialized', {\n filename,\n maxConnections: this.maxConnections,\n acquireTimeoutMs: this.acquireTimeoutMs,\n idleTimeoutMs: this.idleTimeoutMs,\n });\n }\n\n /**\n * Acquire a connection from the pool\n */\n async acquire(): Promise<PooledConnection> {\n const startTime = Date.now();\n \n while (Date.now() - startTime < this.acquireTimeoutMs) {\n // Try to find an idle connection\n for (const [id, connection] of this.connections) {\n if (!connection.inUse) {\n connection.inUse = true;\n connection.lastUsed = Date.now();\n this.stats.totalAcquired++;\n this.stats.currentActive++;\n this.stats.currentIdle--;\n \n logger.debug('Reused connection from pool', { connectionId: id });\n return connection;\n }\n }\n\n // Create new connection if under limit\n if (this.connections.size < this.maxConnections) {\n return this.createConnection();\n }\n\n // Wait briefly before retrying\n await new Promise(resolve => setTimeout(resolve, 10));\n }\n\n throw new Error(`Failed to acquire connection within ${this.acquireTimeoutMs}ms timeout`);\n }\n\n /**\n * Release a connection back to the pool\n */\n release(connection: PooledConnection): void {\n if (this.connections.has(connection.id)) {\n connection.inUse = false;\n connection.lastUsed = Date.now();\n this.stats.totalReleased++;\n this.stats.currentActive--;\n this.stats.currentIdle++;\n \n logger.debug('Released connection to pool', { connectionId: connection.id });\n }\n }\n\n /**\n * Execute a function with a pooled connection\n */\n async withConnection<T>(fn: (db: Database.Database) => T | Promise<T>): Promise<T> {\n const connection = await this.acquire();\n try {\n return await fn(connection.db);\n } finally {\n this.release(connection);\n }\n }\n\n /**\n * Execute a transaction with a pooled connection\n */\n async withTransaction<T>(fn: (db: Database.Database) => T): Promise<T> {\n const connection = await this.acquire();\n try {\n const transaction = connection.db.transaction(() => fn(connection.db));\n return transaction();\n } finally {\n this.release(connection);\n }\n }\n\n /**\n * Get pool statistics\n */\n getStats() {\n return {\n ...this.stats,\n totalConnections: this.connections.size,\n maxConnections: this.maxConnections,\n };\n }\n\n /**\n * Close all connections and cleanup\n */\n async close(): Promise<void> {\n if (this.cleanupInterval) {\n clearInterval(this.cleanupInterval);\n this.cleanupInterval = null;\n }\n\n for (const [id, connection] of this.connections) {\n try {\n connection.db.close();\n logger.debug('Closed connection', { connectionId: id });\n } catch (error) {\n logger.warn('Error closing connection', {\n connectionId: id,\n error: (error as Error).message,\n });\n }\n }\n\n this.connections.clear();\n this.stats.currentActive = 0;\n this.stats.currentIdle = 0;\n \n logger.info('Connection pool closed', { \n totalCreated: this.stats.totalCreated,\n totalAcquired: this.stats.totalAcquired,\n totalReleased: this.stats.totalReleased,\n });\n }\n\n /**\n * Create a new connection\n */\n private createConnection(): PooledConnection {\n const id = `conn_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\n const now = Date.now();\n \n const db = createTracedDatabase(this.filename, this.options);\n \n // Configure for performance\n db.pragma('journal_mode = WAL');\n db.pragma('synchronous = NORMAL');\n db.pragma('cache_size = 1000');\n db.pragma('temp_store = MEMORY');\n \n const connection: PooledConnection = {\n db,\n id,\n createdAt: now,\n lastUsed: now,\n inUse: true,\n };\n\n this.connections.set(id, connection);\n this.stats.totalCreated++;\n this.stats.totalAcquired++;\n this.stats.currentActive++;\n\n logger.debug('Created new connection', { \n connectionId: id,\n totalConnections: this.connections.size,\n });\n\n return connection;\n }\n\n /**\n * Clean up idle connections\n */\n private cleanup(): void {\n const now = Date.now();\n const toRemove: string[] = [];\n\n for (const [id, connection] of this.connections) {\n if (!connection.inUse && now - connection.lastUsed > this.idleTimeoutMs) {\n toRemove.push(id);\n }\n }\n\n for (const id of toRemove) {\n const connection = this.connections.get(id);\n if (connection) {\n try {\n connection.db.close();\n this.connections.delete(id);\n this.stats.currentIdle--;\n \n logger.debug('Cleaned up idle connection', { \n connectionId: id,\n idleTime: now - connection.lastUsed,\n });\n } catch (error) {\n logger.warn('Error cleaning up connection', {\n connectionId: id,\n error: (error as Error).message,\n });\n }\n }\n }\n\n if (toRemove.length > 0) {\n logger.info('Connection cleanup completed', {\n removed: toRemove.length,\n remaining: this.connections.size,\n });\n }\n }\n}\n\n// Global pool instance\nlet globalPool: SQLiteConnectionPool | null = null;\n\n/**\n * Get or create the global connection pool\n */\nexport function getConnectionPool(\n filename?: string, \n options?: ConnectionPoolOptions\n): SQLiteConnectionPool {\n if (!globalPool && filename) {\n globalPool = new SQLiteConnectionPool(filename, options);\n }\n \n if (!globalPool) {\n throw new Error('Connection pool not initialized. Call with filename first.');\n }\n \n return globalPool;\n}\n\n/**\n * Close the global connection pool\n */\nexport async function closeGlobalPool(): Promise<void> {\n if (globalPool) {\n await globalPool.close();\n globalPool = null;\n }\n}"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|