specweave 0.28.68 → 0.29.1
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/CLAUDE.md +3 -2
- package/README.md +19 -2
- package/dist/src/cli/commands/discrepancies.d.ts +89 -0
- package/dist/src/cli/commands/discrepancies.d.ts.map +1 -0
- package/dist/src/cli/commands/discrepancies.js +385 -0
- package/dist/src/cli/commands/discrepancies.js.map +1 -0
- package/dist/src/cli/commands/notifications.d.ts +70 -0
- package/dist/src/cli/commands/notifications.d.ts.map +1 -0
- package/dist/src/cli/commands/notifications.js +236 -0
- package/dist/src/cli/commands/notifications.js.map +1 -0
- package/dist/src/cli/commands/sync-logs.d.ts +54 -0
- package/dist/src/cli/commands/sync-logs.d.ts.map +1 -0
- package/dist/src/cli/commands/sync-logs.js +240 -0
- package/dist/src/cli/commands/sync-logs.js.map +1 -0
- package/dist/src/cli/commands/sync-monitor.d.ts +42 -0
- package/dist/src/cli/commands/sync-monitor.d.ts.map +1 -0
- package/dist/src/cli/commands/sync-monitor.js +191 -0
- package/dist/src/cli/commands/sync-monitor.js.map +1 -0
- package/dist/src/cli/helpers/init/brownfield-analysis.d.ts +45 -0
- package/dist/src/cli/helpers/init/brownfield-analysis.d.ts.map +1 -0
- package/dist/src/cli/helpers/init/brownfield-analysis.js +431 -0
- package/dist/src/cli/helpers/init/brownfield-analysis.js.map +1 -0
- package/dist/src/cli/helpers/init/index.d.ts +1 -0
- package/dist/src/cli/helpers/init/index.d.ts.map +1 -1
- package/dist/src/cli/helpers/init/index.js +2 -0
- package/dist/src/cli/helpers/init/index.js.map +1 -1
- package/dist/src/cli/workers/brownfield-worker.d.ts +66 -0
- package/dist/src/cli/workers/brownfield-worker.d.ts.map +1 -0
- package/dist/src/cli/workers/brownfield-worker.js +417 -0
- package/dist/src/cli/workers/brownfield-worker.js.map +1 -0
- package/dist/src/core/background/brownfield-launcher.d.ts +86 -0
- package/dist/src/core/background/brownfield-launcher.d.ts.map +1 -0
- package/dist/src/core/background/brownfield-launcher.js +295 -0
- package/dist/src/core/background/brownfield-launcher.js.map +1 -0
- package/dist/src/core/background/index.d.ts +2 -0
- package/dist/src/core/background/index.d.ts.map +1 -1
- package/dist/src/core/background/index.js +2 -0
- package/dist/src/core/background/index.js.map +1 -1
- package/dist/src/core/background/types.d.ts +23 -2
- package/dist/src/core/background/types.d.ts.map +1 -1
- package/dist/src/core/config/index.d.ts +1 -0
- package/dist/src/core/config/index.d.ts.map +1 -1
- package/dist/src/core/config/index.js +1 -0
- package/dist/src/core/config/index.js.map +1 -1
- package/dist/src/core/config/types.d.ts +6 -0
- package/dist/src/core/config/types.d.ts.map +1 -1
- package/dist/src/core/config/types.js.map +1 -1
- package/dist/src/core/dashboard/dashboard-data.d.ts +156 -0
- package/dist/src/core/dashboard/dashboard-data.d.ts.map +1 -0
- package/dist/src/core/dashboard/dashboard-data.js +191 -0
- package/dist/src/core/dashboard/dashboard-data.js.map +1 -0
- package/dist/src/core/dashboard/index.d.ts +9 -0
- package/dist/src/core/dashboard/index.d.ts.map +1 -0
- package/dist/src/core/dashboard/index.js +9 -0
- package/dist/src/core/dashboard/index.js.map +1 -0
- package/dist/src/core/discrepancy/analyzers/api-route-analyzer.d.ts +77 -0
- package/dist/src/core/discrepancy/analyzers/api-route-analyzer.d.ts.map +1 -0
- package/dist/src/core/discrepancy/analyzers/api-route-analyzer.js +286 -0
- package/dist/src/core/discrepancy/analyzers/api-route-analyzer.js.map +1 -0
- package/dist/src/core/discrepancy/analyzers/index.d.ts +8 -0
- package/dist/src/core/discrepancy/analyzers/index.d.ts.map +1 -0
- package/dist/src/core/discrepancy/analyzers/index.js +8 -0
- package/dist/src/core/discrepancy/analyzers/index.js.map +1 -0
- package/dist/src/core/discrepancy/analyzers/typescript-analyzer.d.ts +96 -0
- package/dist/src/core/discrepancy/analyzers/typescript-analyzer.d.ts.map +1 -0
- package/dist/src/core/discrepancy/analyzers/typescript-analyzer.js +247 -0
- package/dist/src/core/discrepancy/analyzers/typescript-analyzer.js.map +1 -0
- package/dist/src/core/discrepancy/brownfield-manager.d.ts +88 -0
- package/dist/src/core/discrepancy/brownfield-manager.d.ts.map +1 -0
- package/dist/src/core/discrepancy/brownfield-manager.js +520 -0
- package/dist/src/core/discrepancy/brownfield-manager.js.map +1 -0
- package/dist/src/core/discrepancy/brownfield-types.d.ts +174 -0
- package/dist/src/core/discrepancy/brownfield-types.d.ts.map +1 -0
- package/dist/src/core/discrepancy/brownfield-types.js +11 -0
- package/dist/src/core/discrepancy/brownfield-types.js.map +1 -0
- package/dist/src/core/discrepancy/detector.d.ts +92 -0
- package/dist/src/core/discrepancy/detector.d.ts.map +1 -0
- package/dist/src/core/discrepancy/detector.js +346 -0
- package/dist/src/core/discrepancy/detector.js.map +1 -0
- package/dist/src/core/discrepancy/increment-generator.d.ts +51 -0
- package/dist/src/core/discrepancy/increment-generator.d.ts.map +1 -0
- package/dist/src/core/discrepancy/increment-generator.js +234 -0
- package/dist/src/core/discrepancy/increment-generator.js.map +1 -0
- package/dist/src/core/discrepancy/index.d.ts +18 -0
- package/dist/src/core/discrepancy/index.d.ts.map +1 -0
- package/dist/src/core/discrepancy/index.js +24 -0
- package/dist/src/core/discrepancy/index.js.map +1 -0
- package/dist/src/core/discrepancy/severity-classifier.d.ts +81 -0
- package/dist/src/core/discrepancy/severity-classifier.d.ts.map +1 -0
- package/dist/src/core/discrepancy/severity-classifier.js +289 -0
- package/dist/src/core/discrepancy/severity-classifier.js.map +1 -0
- package/dist/src/core/discrepancy/spec-parser.d.ts +74 -0
- package/dist/src/core/discrepancy/spec-parser.d.ts.map +1 -0
- package/dist/src/core/discrepancy/spec-parser.js +213 -0
- package/dist/src/core/discrepancy/spec-parser.js.map +1 -0
- package/dist/src/core/discrepancy/update-recommender.d.ts +77 -0
- package/dist/src/core/discrepancy/update-recommender.d.ts.map +1 -0
- package/dist/src/core/discrepancy/update-recommender.js +323 -0
- package/dist/src/core/discrepancy/update-recommender.js.map +1 -0
- package/dist/src/core/living-docs/living-docs-sync.d.ts +13 -16
- package/dist/src/core/living-docs/living-docs-sync.d.ts.map +1 -1
- package/dist/src/core/living-docs/living-docs-sync.js +31 -112
- package/dist/src/core/living-docs/living-docs-sync.js.map +1 -1
- package/dist/src/core/logs/index.d.ts +10 -0
- package/dist/src/core/logs/index.d.ts.map +1 -0
- package/dist/src/core/logs/index.js +10 -0
- package/dist/src/core/logs/index.js.map +1 -0
- package/dist/src/core/logs/log-aggregator.d.ts +130 -0
- package/dist/src/core/logs/log-aggregator.d.ts.map +1 -0
- package/dist/src/core/logs/log-aggregator.js +206 -0
- package/dist/src/core/logs/log-aggregator.js.map +1 -0
- package/dist/src/core/logs/log-exporter.d.ts +81 -0
- package/dist/src/core/logs/log-exporter.d.ts.map +1 -0
- package/dist/src/core/logs/log-exporter.js +141 -0
- package/dist/src/core/logs/log-exporter.js.map +1 -0
- package/dist/src/core/notifications/command-integration.d.ts +82 -0
- package/dist/src/core/notifications/command-integration.d.ts.map +1 -0
- package/dist/src/core/notifications/command-integration.js +80 -0
- package/dist/src/core/notifications/command-integration.js.map +1 -0
- package/dist/src/core/notifications/index.d.ts +12 -0
- package/dist/src/core/notifications/index.d.ts.map +1 -0
- package/dist/src/core/notifications/index.js +12 -0
- package/dist/src/core/notifications/index.js.map +1 -0
- package/dist/src/core/notifications/notification-display.d.ts +70 -0
- package/dist/src/core/notifications/notification-display.d.ts.map +1 -0
- package/dist/src/core/notifications/notification-display.js +177 -0
- package/dist/src/core/notifications/notification-display.js.map +1 -0
- package/dist/src/core/notifications/notification-manager.d.ts +126 -0
- package/dist/src/core/notifications/notification-manager.d.ts.map +1 -0
- package/dist/src/core/notifications/notification-manager.js +287 -0
- package/dist/src/core/notifications/notification-manager.js.map +1 -0
- package/dist/src/core/notifications/notification-types.d.ts +159 -0
- package/dist/src/core/notifications/notification-types.d.ts.map +1 -0
- package/dist/src/core/notifications/notification-types.js +93 -0
- package/dist/src/core/notifications/notification-types.js.map +1 -0
- package/dist/src/core/scheduler/index.d.ts +11 -0
- package/dist/src/core/scheduler/index.d.ts.map +1 -0
- package/dist/src/core/scheduler/index.js +11 -0
- package/dist/src/core/scheduler/index.js.map +1 -0
- package/dist/src/core/scheduler/job-scheduler.d.ts +179 -0
- package/dist/src/core/scheduler/job-scheduler.d.ts.map +1 -0
- package/dist/src/core/scheduler/job-scheduler.js +282 -0
- package/dist/src/core/scheduler/job-scheduler.js.map +1 -0
- package/dist/src/core/scheduler/schedule-persistence.d.ts +83 -0
- package/dist/src/core/scheduler/schedule-persistence.d.ts.map +1 -0
- package/dist/src/core/scheduler/schedule-persistence.js +180 -0
- package/dist/src/core/scheduler/schedule-persistence.js.map +1 -0
- package/dist/src/core/scheduler/scheduled-job.d.ts +188 -0
- package/dist/src/core/scheduler/scheduled-job.d.ts.map +1 -0
- package/dist/src/core/scheduler/scheduled-job.js +182 -0
- package/dist/src/core/scheduler/scheduled-job.js.map +1 -0
- package/dist/src/core/sync/permission-enforcer.d.ts +206 -0
- package/dist/src/core/sync/permission-enforcer.d.ts.map +1 -0
- package/dist/src/core/sync/permission-enforcer.js +268 -0
- package/dist/src/core/sync/permission-enforcer.js.map +1 -0
- package/dist/src/core/sync/sync-audit-logger.d.ts +217 -0
- package/dist/src/core/sync/sync-audit-logger.d.ts.map +1 -0
- package/dist/src/core/sync/sync-audit-logger.js +327 -0
- package/dist/src/core/sync/sync-audit-logger.js.map +1 -0
- package/dist/src/core/sync/sync-interceptor.d.ts +190 -0
- package/dist/src/core/sync/sync-interceptor.d.ts.map +1 -0
- package/dist/src/core/sync/sync-interceptor.js +224 -0
- package/dist/src/core/sync/sync-interceptor.js.map +1 -0
- package/dist/src/core/types/increment-metadata.d.ts +5 -2
- package/dist/src/core/types/increment-metadata.d.ts.map +1 -1
- package/dist/src/core/types/sync-config.d.ts +267 -0
- package/dist/src/core/types/sync-config.d.ts.map +1 -0
- package/dist/src/core/types/sync-config.js +304 -0
- package/dist/src/core/types/sync-config.js.map +1 -0
- package/dist/src/hooks/index.d.ts +11 -0
- package/dist/src/hooks/index.d.ts.map +1 -0
- package/dist/src/hooks/index.js +11 -0
- package/dist/src/hooks/index.js.map +1 -0
- package/dist/src/hooks/platform.d.ts +125 -0
- package/dist/src/hooks/platform.d.ts.map +1 -0
- package/dist/src/hooks/platform.js +325 -0
- package/dist/src/hooks/platform.js.map +1 -0
- package/dist/src/hooks/processor.d.ts +20 -0
- package/dist/src/hooks/processor.d.ts.map +1 -0
- package/dist/src/hooks/processor.js +317 -0
- package/dist/src/hooks/processor.js.map +1 -0
- package/dist/src/hooks/scheduler-startup.d.ts +19 -0
- package/dist/src/hooks/scheduler-startup.d.ts.map +1 -0
- package/dist/src/hooks/scheduler-startup.js +92 -0
- package/dist/src/hooks/scheduler-startup.js.map +1 -0
- package/dist/src/hooks/session-start.d.ts +16 -0
- package/dist/src/hooks/session-start.d.ts.map +1 -0
- package/dist/src/hooks/session-start.js +92 -0
- package/dist/src/hooks/session-start.js.map +1 -0
- package/dist/src/importers/duplicate-detector.d.ts +13 -2
- package/dist/src/importers/duplicate-detector.d.ts.map +1 -1
- package/dist/src/importers/duplicate-detector.js +21 -2
- package/dist/src/importers/duplicate-detector.js.map +1 -1
- package/dist/src/importers/item-converter.d.ts +41 -2
- package/dist/src/importers/item-converter.d.ts.map +1 -1
- package/dist/src/importers/item-converter.js +225 -38
- package/dist/src/importers/item-converter.js.map +1 -1
- package/dist/src/living-docs/fs-id-allocator.d.ts +7 -0
- package/dist/src/living-docs/fs-id-allocator.d.ts.map +1 -1
- package/dist/src/living-docs/fs-id-allocator.js +30 -4
- package/dist/src/living-docs/fs-id-allocator.js.map +1 -1
- package/dist/src/sync/ado-sync-wrapper.d.ts +137 -0
- package/dist/src/sync/ado-sync-wrapper.d.ts.map +1 -0
- package/dist/src/sync/ado-sync-wrapper.js +148 -0
- package/dist/src/sync/ado-sync-wrapper.js.map +1 -0
- package/dist/src/sync/github-sync-wrapper.d.ts +195 -0
- package/dist/src/sync/github-sync-wrapper.d.ts.map +1 -0
- package/dist/src/sync/github-sync-wrapper.js +220 -0
- package/dist/src/sync/github-sync-wrapper.js.map +1 -0
- package/dist/src/sync/jira-sync-wrapper.d.ts +155 -0
- package/dist/src/sync/jira-sync-wrapper.d.ts.map +1 -0
- package/dist/src/sync/jira-sync-wrapper.js +175 -0
- package/dist/src/sync/jira-sync-wrapper.js.map +1 -0
- package/dist/src/utils/feature-id-derivation.d.ts +58 -0
- package/dist/src/utils/feature-id-derivation.d.ts.map +1 -0
- package/dist/src/utils/feature-id-derivation.js +77 -0
- package/dist/src/utils/feature-id-derivation.js.map +1 -0
- package/package.json +3 -1
- package/plugins/specweave/commands/specweave-discrepancies.md +141 -0
- package/plugins/specweave/commands/specweave-discrepancy-to-increment.md +160 -0
- package/plugins/specweave/commands/specweave-jobs.md +45 -2
- package/plugins/specweave/commands/specweave-notifications.md +92 -0
- package/plugins/specweave/commands/specweave-sync-logs.md +131 -0
- package/plugins/specweave/commands/specweave-sync-monitor.md +57 -0
- package/plugins/specweave/hooks/hooks.json +3 -3
- package/plugins/specweave/hooks/lib/scheduler-startup.sh +72 -0
- package/plugins/specweave/hooks/universal/dispatcher.mjs +246 -0
- package/plugins/specweave/hooks/universal/session-start.cmd +16 -0
- package/plugins/specweave/hooks/universal/session-start.ps1 +16 -0
- package/plugins/specweave/hooks/v2/dispatchers/session-start.sh +14 -5
- package/plugins/specweave/lib/vendor/core/types/increment-metadata.d.ts +5 -2
- package/plugins/specweave/skills/discrepancy-viewer.md +154 -0
- package/plugins/specweave-github/hooks/.specweave/logs/hooks-debug.log +46 -0
- package/plugins/specweave-release/hooks/.specweave/logs/dora-tracking.log +69 -0
- package/dist/plugins/specweave-github/lib/enhanced-github-sync.d.ts +0 -26
- package/dist/plugins/specweave-github/lib/enhanced-github-sync.d.ts.map +0 -1
- package/dist/plugins/specweave-github/lib/enhanced-github-sync.js +0 -249
- package/dist/plugins/specweave-github/lib/enhanced-github-sync.js.map +0 -1
- package/dist/plugins/specweave-jira/lib/enhanced-jira-sync.d.ts +0 -28
- package/dist/plugins/specweave-jira/lib/enhanced-jira-sync.d.ts.map +0 -1
- package/dist/plugins/specweave-jira/lib/enhanced-jira-sync.js +0 -156
- package/dist/plugins/specweave-jira/lib/enhanced-jira-sync.js.map +0 -1
- package/dist/src/core/sync/bidirectional-engine.d.ts +0 -119
- package/dist/src/core/sync/bidirectional-engine.d.ts.map +0 -1
- package/dist/src/core/sync/bidirectional-engine.js +0 -359
- package/dist/src/core/sync/bidirectional-engine.js.map +0 -1
- package/dist/src/core/sync/conflict-resolver.d.ts +0 -66
- package/dist/src/core/sync/conflict-resolver.d.ts.map +0 -1
- package/dist/src/core/sync/conflict-resolver.js +0 -108
- package/dist/src/core/sync/conflict-resolver.js.map +0 -1
- package/dist/src/core/sync/enhanced-content-builder.d.ts +0 -55
- package/dist/src/core/sync/enhanced-content-builder.d.ts.map +0 -1
- package/dist/src/core/sync/enhanced-content-builder.js +0 -203
- package/dist/src/core/sync/enhanced-content-builder.js.map +0 -1
- package/dist/src/core/sync/folder-mapper.d.ts +0 -71
- package/dist/src/core/sync/folder-mapper.d.ts.map +0 -1
- package/dist/src/core/sync/folder-mapper.js +0 -203
- package/dist/src/core/sync/folder-mapper.js.map +0 -1
- package/dist/src/core/sync/label-detector.d.ts +0 -66
- package/dist/src/core/sync/label-detector.d.ts.map +0 -1
- package/dist/src/core/sync/label-detector.js +0 -224
- package/dist/src/core/sync/label-detector.js.map +0 -1
- package/dist/src/core/sync/performance-optimizer.d.ts +0 -153
- package/dist/src/core/sync/performance-optimizer.d.ts.map +0 -1
- package/dist/src/core/sync/performance-optimizer.js +0 -220
- package/dist/src/core/sync/performance-optimizer.js.map +0 -1
- package/dist/src/core/sync/profile-selector.d.ts +0 -52
- package/dist/src/core/sync/profile-selector.d.ts.map +0 -1
- package/dist/src/core/sync/profile-selector.js +0 -179
- package/dist/src/core/sync/profile-selector.js.map +0 -1
- package/dist/src/core/sync/profile-validator.d.ts +0 -52
- package/dist/src/core/sync/profile-validator.d.ts.map +0 -1
- package/dist/src/core/sync/profile-validator.js +0 -170
- package/dist/src/core/sync/profile-validator.js.map +0 -1
- package/dist/src/core/sync/rate-limiter.d.ts +0 -116
- package/dist/src/core/sync/rate-limiter.d.ts.map +0 -1
- package/dist/src/core/sync/rate-limiter.js +0 -308
- package/dist/src/core/sync/rate-limiter.js.map +0 -1
- package/dist/src/core/sync/retry-handler.d.ts +0 -98
- package/dist/src/core/sync/retry-handler.d.ts.map +0 -1
- package/dist/src/core/sync/retry-handler.js +0 -196
- package/dist/src/core/sync/retry-handler.js.map +0 -1
- package/dist/src/core/sync/retry-logic.d.ts +0 -64
- package/dist/src/core/sync/retry-logic.d.ts.map +0 -1
- package/dist/src/core/sync/retry-logic.js +0 -165
- package/dist/src/core/sync/retry-logic.js.map +0 -1
- package/dist/src/core/sync/status-cache.d.ts +0 -91
- package/dist/src/core/sync/status-cache.d.ts.map +0 -1
- package/dist/src/core/sync/status-cache.js +0 -140
- package/dist/src/core/sync/status-cache.js.map +0 -1
- package/dist/src/core/sync/status-mapper.d.ts +0 -69
- package/dist/src/core/sync/status-mapper.d.ts.map +0 -1
- package/dist/src/core/sync/status-mapper.js +0 -90
- package/dist/src/core/sync/status-mapper.js.map +0 -1
- package/dist/src/core/sync/status-sync-engine.d.ts +0 -162
- package/dist/src/core/sync/status-sync-engine.d.ts.map +0 -1
- package/dist/src/core/sync/status-sync-engine.js +0 -347
- package/dist/src/core/sync/status-sync-engine.js.map +0 -1
- package/dist/src/core/sync/sync-event-logger.d.ts +0 -113
- package/dist/src/core/sync/sync-event-logger.d.ts.map +0 -1
- package/dist/src/core/sync/sync-event-logger.js +0 -141
- package/dist/src/core/sync/sync-event-logger.js.map +0 -1
- package/dist/src/core/sync/time-range-selector.d.ts +0 -48
- package/dist/src/core/sync/time-range-selector.d.ts.map +0 -1
- package/dist/src/core/sync/time-range-selector.js +0 -224
- package/dist/src/core/sync/time-range-selector.js.map +0 -1
- package/dist/src/core/sync/types.d.ts +0 -52
- package/dist/src/core/sync/types.d.ts.map +0 -1
- package/dist/src/core/sync/types.js +0 -5
- package/dist/src/core/sync/types.js.map +0 -1
- package/dist/src/core/sync/workflow-detector.d.ts +0 -95
- package/dist/src/core/sync/workflow-detector.d.ts.map +0 -1
- package/dist/src/core/sync/workflow-detector.js +0 -175
- package/dist/src/core/sync/workflow-detector.js.map +0 -1
- package/plugins/specweave-github/lib/enhanced-github-sync.js +0 -220
- package/plugins/specweave-github/lib/enhanced-github-sync.ts +0 -322
- package/plugins/specweave-jira/lib/enhanced-jira-sync.js +0 -134
- package/plugins/specweave-jira/lib/enhanced-jira-sync.ts +0 -196
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scheduler Module
|
|
3
|
+
*
|
|
4
|
+
* Exports job scheduling functionality for the sync orchestration system.
|
|
5
|
+
*
|
|
6
|
+
* @module core/scheduler
|
|
7
|
+
*/
|
|
8
|
+
export * from './scheduled-job.js';
|
|
9
|
+
export * from './job-scheduler.js';
|
|
10
|
+
export * from './schedule-persistence.js';
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/core/scheduler/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,2BAA2B,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scheduler Module
|
|
3
|
+
*
|
|
4
|
+
* Exports job scheduling functionality for the sync orchestration system.
|
|
5
|
+
*
|
|
6
|
+
* @module core/scheduler
|
|
7
|
+
*/
|
|
8
|
+
export * from './scheduled-job.js';
|
|
9
|
+
export * from './job-scheduler.js';
|
|
10
|
+
export * from './schedule-persistence.js';
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/core/scheduler/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,2BAA2B,CAAC"}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Job Scheduler
|
|
3
|
+
*
|
|
4
|
+
* Core scheduler that manages recurring jobs with configurable intervals.
|
|
5
|
+
* Supports pause/resume, retry with backoff, and job state tracking.
|
|
6
|
+
*
|
|
7
|
+
* @module core/scheduler/job-scheduler
|
|
8
|
+
*/
|
|
9
|
+
import { ScheduledJob, ScheduledJobConfig, JobType } from './scheduled-job.js';
|
|
10
|
+
import { Logger } from '../../utils/logger.js';
|
|
11
|
+
/**
|
|
12
|
+
* Job scheduler configuration
|
|
13
|
+
*/
|
|
14
|
+
export interface JobSchedulerOptions {
|
|
15
|
+
/**
|
|
16
|
+
* Logger instance
|
|
17
|
+
*/
|
|
18
|
+
logger?: Logger;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Job scheduler events
|
|
22
|
+
*/
|
|
23
|
+
export type JobSchedulerEvent = 'job-registered' | 'job-unregistered' | 'job-started' | 'job-completed' | 'job-failed' | 'job-paused' | 'job-resumed';
|
|
24
|
+
/**
|
|
25
|
+
* Event listener callback
|
|
26
|
+
*/
|
|
27
|
+
export type JobSchedulerEventListener = (event: JobSchedulerEvent, job: ScheduledJob, data?: Record<string, unknown>) => void;
|
|
28
|
+
/**
|
|
29
|
+
* JobScheduler - Manages recurring background jobs
|
|
30
|
+
*
|
|
31
|
+
* Key features:
|
|
32
|
+
* - Register/unregister jobs dynamically
|
|
33
|
+
* - Check for due jobs (for execution by caller)
|
|
34
|
+
* - Track job state (idle, running, failed, disabled)
|
|
35
|
+
* - Exponential backoff for failed jobs
|
|
36
|
+
* - Event notifications for state changes
|
|
37
|
+
*/
|
|
38
|
+
export declare class JobScheduler {
|
|
39
|
+
private jobs;
|
|
40
|
+
private listeners;
|
|
41
|
+
private readonly logger;
|
|
42
|
+
constructor(options?: JobSchedulerOptions);
|
|
43
|
+
/**
|
|
44
|
+
* Register a new job with the scheduler
|
|
45
|
+
*
|
|
46
|
+
* @param config - Job configuration
|
|
47
|
+
* @throws Error if job with same ID already exists
|
|
48
|
+
*/
|
|
49
|
+
registerJob(config: ScheduledJobConfig): void;
|
|
50
|
+
/**
|
|
51
|
+
* Unregister a job from the scheduler
|
|
52
|
+
*
|
|
53
|
+
* @param jobId - Job ID to remove
|
|
54
|
+
* @returns true if job was removed, false if not found
|
|
55
|
+
*/
|
|
56
|
+
unregisterJob(jobId: string): boolean;
|
|
57
|
+
/**
|
|
58
|
+
* Get a job by ID
|
|
59
|
+
*
|
|
60
|
+
* @param jobId - Job ID
|
|
61
|
+
* @returns Job or undefined if not found
|
|
62
|
+
*/
|
|
63
|
+
getJob(jobId: string): ScheduledJob | undefined;
|
|
64
|
+
/**
|
|
65
|
+
* Get all registered jobs
|
|
66
|
+
*
|
|
67
|
+
* @returns Array of all jobs
|
|
68
|
+
*/
|
|
69
|
+
getAllJobs(): ScheduledJob[];
|
|
70
|
+
/**
|
|
71
|
+
* Get jobs by type
|
|
72
|
+
*
|
|
73
|
+
* @param type - Job type to filter by
|
|
74
|
+
* @returns Array of matching jobs
|
|
75
|
+
*/
|
|
76
|
+
getJobsByType(type: JobType): ScheduledJob[];
|
|
77
|
+
/**
|
|
78
|
+
* Get all jobs that are due for execution
|
|
79
|
+
*
|
|
80
|
+
* @returns Array of due jobs (sorted by next run time)
|
|
81
|
+
*/
|
|
82
|
+
getNextDueJobs(): ScheduledJob[];
|
|
83
|
+
/**
|
|
84
|
+
* Mark a job as started (running)
|
|
85
|
+
*
|
|
86
|
+
* @param jobId - Job ID
|
|
87
|
+
* @throws Error if job not found or not in idle state
|
|
88
|
+
*/
|
|
89
|
+
markJobStarted(jobId: string): void;
|
|
90
|
+
/**
|
|
91
|
+
* Mark a job as completed successfully
|
|
92
|
+
*
|
|
93
|
+
* @param jobId - Job ID
|
|
94
|
+
* @param data - Optional result data
|
|
95
|
+
* @throws Error if job not found
|
|
96
|
+
*/
|
|
97
|
+
markJobComplete(jobId: string, data?: Record<string, unknown>): void;
|
|
98
|
+
/**
|
|
99
|
+
* Mark a job as failed
|
|
100
|
+
*
|
|
101
|
+
* @param jobId - Job ID
|
|
102
|
+
* @param error - Error message
|
|
103
|
+
* @throws Error if job not found
|
|
104
|
+
*/
|
|
105
|
+
markJobFailed(jobId: string, error: string): void;
|
|
106
|
+
/**
|
|
107
|
+
* Pause a job (stops scheduling but preserves state)
|
|
108
|
+
*
|
|
109
|
+
* @param jobId - Job ID
|
|
110
|
+
* @throws Error if job not found
|
|
111
|
+
*/
|
|
112
|
+
pauseJob(jobId: string): void;
|
|
113
|
+
/**
|
|
114
|
+
* Resume a paused job
|
|
115
|
+
*
|
|
116
|
+
* @param jobId - Job ID
|
|
117
|
+
* @throws Error if job not found
|
|
118
|
+
*/
|
|
119
|
+
resumeJob(jobId: string): void;
|
|
120
|
+
/**
|
|
121
|
+
* Reset a failed job for retry
|
|
122
|
+
*
|
|
123
|
+
* @param jobId - Job ID
|
|
124
|
+
* @throws Error if job not found
|
|
125
|
+
*/
|
|
126
|
+
resetJob(jobId: string): void;
|
|
127
|
+
/**
|
|
128
|
+
* Update job interval
|
|
129
|
+
*
|
|
130
|
+
* @param jobId - Job ID
|
|
131
|
+
* @param intervalMs - New interval in milliseconds
|
|
132
|
+
* @throws Error if job not found
|
|
133
|
+
*/
|
|
134
|
+
updateJobInterval(jobId: string, intervalMs: number): void;
|
|
135
|
+
/**
|
|
136
|
+
* Load jobs from persisted state
|
|
137
|
+
*
|
|
138
|
+
* @param jobs - Array of persisted jobs
|
|
139
|
+
*/
|
|
140
|
+
loadJobs(jobs: ScheduledJob[]): void;
|
|
141
|
+
/**
|
|
142
|
+
* Get all jobs for persistence
|
|
143
|
+
*
|
|
144
|
+
* @returns Array of all jobs
|
|
145
|
+
*/
|
|
146
|
+
getJobsForPersistence(): ScheduledJob[];
|
|
147
|
+
/**
|
|
148
|
+
* Add an event listener
|
|
149
|
+
*
|
|
150
|
+
* @param listener - Callback function
|
|
151
|
+
*/
|
|
152
|
+
addEventListener(listener: JobSchedulerEventListener): void;
|
|
153
|
+
/**
|
|
154
|
+
* Remove an event listener
|
|
155
|
+
*
|
|
156
|
+
* @param listener - Callback function
|
|
157
|
+
*/
|
|
158
|
+
removeEventListener(listener: JobSchedulerEventListener): void;
|
|
159
|
+
/**
|
|
160
|
+
* Get scheduler statistics
|
|
161
|
+
*
|
|
162
|
+
* @returns Scheduler stats
|
|
163
|
+
*/
|
|
164
|
+
getStats(): {
|
|
165
|
+
totalJobs: number;
|
|
166
|
+
byStatus: Record<string, number>;
|
|
167
|
+
byType: Record<string, number>;
|
|
168
|
+
dueCount: number;
|
|
169
|
+
};
|
|
170
|
+
/**
|
|
171
|
+
* Emit an event to all listeners
|
|
172
|
+
*/
|
|
173
|
+
private emit;
|
|
174
|
+
/**
|
|
175
|
+
* Get a job or throw if not found
|
|
176
|
+
*/
|
|
177
|
+
private getJobOrThrow;
|
|
178
|
+
}
|
|
179
|
+
//# sourceMappingURL=job-scheduler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"job-scheduler.d.ts","sourceRoot":"","sources":["../../../../src/core/scheduler/job-scheduler.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,OAAO,EASR,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,MAAM,EAAiB,MAAM,uBAAuB,CAAC;AAE9D;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,MAAM,iBAAiB,GACzB,gBAAgB,GAChB,kBAAkB,GAClB,aAAa,GACb,eAAe,GACf,YAAY,GACZ,YAAY,GACZ,aAAa,CAAC;AAElB;;GAEG;AACH,MAAM,MAAM,yBAAyB,GAAG,CACtC,KAAK,EAAE,iBAAiB,EACxB,GAAG,EAAE,YAAY,EACjB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC3B,IAAI,CAAC;AAEV;;;;;;;;;GASG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,IAAI,CAA4B;IACxC,OAAO,CAAC,SAAS,CAAiC;IAClD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;gBAEpB,OAAO,GAAE,mBAAwB;IAM7C;;;;;OAKG;IACH,WAAW,CAAC,MAAM,EAAE,kBAAkB,GAAG,IAAI;IAY7C;;;;;OAKG;IACH,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAYrC;;;;;OAKG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;IAI/C;;;;OAIG;IACH,UAAU,IAAI,YAAY,EAAE;IAI5B;;;;;OAKG;IACH,aAAa,CAAC,IAAI,EAAE,OAAO,GAAG,YAAY,EAAE;IAI5C;;;;OAIG;IACH,cAAc,IAAI,YAAY,EAAE;IAWhC;;;;;OAKG;IACH,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAcnC;;;;;;OAMG;IACH,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAUpE;;;;;;OAMG;IACH,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAcjD;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAU7B;;;;;OAKG;IACH,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAU9B;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAS7B;;;;;;OAMG;IACH,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI;IAe1D;;;;OAIG;IACH,QAAQ,CAAC,IAAI,EAAE,YAAY,EAAE,GAAG,IAAI;IAQpC;;;;OAIG;IACH,qBAAqB,IAAI,YAAY,EAAE;IAIvC;;;;OAIG;IACH,gBAAgB,CAAC,QAAQ,EAAE,yBAAyB,GAAG,IAAI;IAI3D;;;;OAIG;IACH,mBAAmB,CAAC,QAAQ,EAAE,yBAAyB,GAAG,IAAI;IAI9D;;;;OAIG;IACH,QAAQ,IAAI;QACV,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACjC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC/B,QAAQ,EAAE,MAAM,CAAC;KAClB;IAkBD;;OAEG;IACH,OAAO,CAAC,IAAI;IAcZ;;OAEG;IACH,OAAO,CAAC,aAAa;CAOtB"}
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Job Scheduler
|
|
3
|
+
*
|
|
4
|
+
* Core scheduler that manages recurring jobs with configurable intervals.
|
|
5
|
+
* Supports pause/resume, retry with backoff, and job state tracking.
|
|
6
|
+
*
|
|
7
|
+
* @module core/scheduler/job-scheduler
|
|
8
|
+
*/
|
|
9
|
+
import { createScheduledJob, isJobDue, markJobComplete, markJobFailed, markJobRunning, pauseJob, resumeJob, resetJob, } from './scheduled-job.js';
|
|
10
|
+
import { consoleLogger } from '../../utils/logger.js';
|
|
11
|
+
/**
|
|
12
|
+
* JobScheduler - Manages recurring background jobs
|
|
13
|
+
*
|
|
14
|
+
* Key features:
|
|
15
|
+
* - Register/unregister jobs dynamically
|
|
16
|
+
* - Check for due jobs (for execution by caller)
|
|
17
|
+
* - Track job state (idle, running, failed, disabled)
|
|
18
|
+
* - Exponential backoff for failed jobs
|
|
19
|
+
* - Event notifications for state changes
|
|
20
|
+
*/
|
|
21
|
+
export class JobScheduler {
|
|
22
|
+
constructor(options = {}) {
|
|
23
|
+
this.jobs = new Map();
|
|
24
|
+
this.listeners = new Set();
|
|
25
|
+
this.logger = options.logger ?? consoleLogger;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Register a new job with the scheduler
|
|
29
|
+
*
|
|
30
|
+
* @param config - Job configuration
|
|
31
|
+
* @throws Error if job with same ID already exists
|
|
32
|
+
*/
|
|
33
|
+
registerJob(config) {
|
|
34
|
+
if (this.jobs.has(config.id)) {
|
|
35
|
+
throw new Error(`Job with ID "${config.id}" already registered`);
|
|
36
|
+
}
|
|
37
|
+
const job = createScheduledJob(config);
|
|
38
|
+
this.jobs.set(config.id, job);
|
|
39
|
+
this.logger.debug(`Registered job: ${config.id} (interval: ${config.intervalMs}ms)`);
|
|
40
|
+
this.emit('job-registered', job);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Unregister a job from the scheduler
|
|
44
|
+
*
|
|
45
|
+
* @param jobId - Job ID to remove
|
|
46
|
+
* @returns true if job was removed, false if not found
|
|
47
|
+
*/
|
|
48
|
+
unregisterJob(jobId) {
|
|
49
|
+
const job = this.jobs.get(jobId);
|
|
50
|
+
if (!job) {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
this.jobs.delete(jobId);
|
|
54
|
+
this.logger.debug(`Unregistered job: ${jobId}`);
|
|
55
|
+
this.emit('job-unregistered', job);
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Get a job by ID
|
|
60
|
+
*
|
|
61
|
+
* @param jobId - Job ID
|
|
62
|
+
* @returns Job or undefined if not found
|
|
63
|
+
*/
|
|
64
|
+
getJob(jobId) {
|
|
65
|
+
return this.jobs.get(jobId);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Get all registered jobs
|
|
69
|
+
*
|
|
70
|
+
* @returns Array of all jobs
|
|
71
|
+
*/
|
|
72
|
+
getAllJobs() {
|
|
73
|
+
return Array.from(this.jobs.values());
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Get jobs by type
|
|
77
|
+
*
|
|
78
|
+
* @param type - Job type to filter by
|
|
79
|
+
* @returns Array of matching jobs
|
|
80
|
+
*/
|
|
81
|
+
getJobsByType(type) {
|
|
82
|
+
return this.getAllJobs().filter((job) => job.type === type);
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Get all jobs that are due for execution
|
|
86
|
+
*
|
|
87
|
+
* @returns Array of due jobs (sorted by next run time)
|
|
88
|
+
*/
|
|
89
|
+
getNextDueJobs() {
|
|
90
|
+
const dueJobs = this.getAllJobs().filter(isJobDue);
|
|
91
|
+
// Sort by next run time (earliest first)
|
|
92
|
+
return dueJobs.sort((a, b) => {
|
|
93
|
+
const aTime = a.schedule.nextRun ? new Date(a.schedule.nextRun).getTime() : 0;
|
|
94
|
+
const bTime = b.schedule.nextRun ? new Date(b.schedule.nextRun).getTime() : 0;
|
|
95
|
+
return aTime - bTime;
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Mark a job as started (running)
|
|
100
|
+
*
|
|
101
|
+
* @param jobId - Job ID
|
|
102
|
+
* @throws Error if job not found or not in idle state
|
|
103
|
+
*/
|
|
104
|
+
markJobStarted(jobId) {
|
|
105
|
+
const job = this.getJobOrThrow(jobId);
|
|
106
|
+
if (job.status !== 'idle') {
|
|
107
|
+
throw new Error(`Cannot start job "${jobId}" - status is "${job.status}", expected "idle"`);
|
|
108
|
+
}
|
|
109
|
+
const updatedJob = markJobRunning(job);
|
|
110
|
+
this.jobs.set(jobId, updatedJob);
|
|
111
|
+
this.logger.debug(`Job started: ${jobId}`);
|
|
112
|
+
this.emit('job-started', updatedJob);
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Mark a job as completed successfully
|
|
116
|
+
*
|
|
117
|
+
* @param jobId - Job ID
|
|
118
|
+
* @param data - Optional result data
|
|
119
|
+
* @throws Error if job not found
|
|
120
|
+
*/
|
|
121
|
+
markJobComplete(jobId, data) {
|
|
122
|
+
const job = this.getJobOrThrow(jobId);
|
|
123
|
+
const updatedJob = markJobComplete(job);
|
|
124
|
+
this.jobs.set(jobId, updatedJob);
|
|
125
|
+
this.logger.debug(`Job completed: ${jobId}, next run: ${updatedJob.schedule.nextRun}`);
|
|
126
|
+
this.emit('job-completed', updatedJob, data);
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Mark a job as failed
|
|
130
|
+
*
|
|
131
|
+
* @param jobId - Job ID
|
|
132
|
+
* @param error - Error message
|
|
133
|
+
* @throws Error if job not found
|
|
134
|
+
*/
|
|
135
|
+
markJobFailed(jobId, error) {
|
|
136
|
+
const job = this.getJobOrThrow(jobId);
|
|
137
|
+
const updatedJob = markJobFailed(job, error);
|
|
138
|
+
this.jobs.set(jobId, updatedJob);
|
|
139
|
+
const retryInfo = updatedJob.status === 'failed'
|
|
140
|
+
? 'max retries reached'
|
|
141
|
+
: `retry ${updatedJob.schedule.retryCount}/${updatedJob.schedule.maxRetries}`;
|
|
142
|
+
this.logger.warn(`Job failed: ${jobId} - ${error} (${retryInfo})`);
|
|
143
|
+
this.emit('job-failed', updatedJob, { error });
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Pause a job (stops scheduling but preserves state)
|
|
147
|
+
*
|
|
148
|
+
* @param jobId - Job ID
|
|
149
|
+
* @throws Error if job not found
|
|
150
|
+
*/
|
|
151
|
+
pauseJob(jobId) {
|
|
152
|
+
const job = this.getJobOrThrow(jobId);
|
|
153
|
+
const updatedJob = pauseJob(job);
|
|
154
|
+
this.jobs.set(jobId, updatedJob);
|
|
155
|
+
this.logger.debug(`Job paused: ${jobId}`);
|
|
156
|
+
this.emit('job-paused', updatedJob);
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Resume a paused job
|
|
160
|
+
*
|
|
161
|
+
* @param jobId - Job ID
|
|
162
|
+
* @throws Error if job not found
|
|
163
|
+
*/
|
|
164
|
+
resumeJob(jobId) {
|
|
165
|
+
const job = this.getJobOrThrow(jobId);
|
|
166
|
+
const updatedJob = resumeJob(job);
|
|
167
|
+
this.jobs.set(jobId, updatedJob);
|
|
168
|
+
this.logger.debug(`Job resumed: ${jobId}, next run: ${updatedJob.schedule.nextRun}`);
|
|
169
|
+
this.emit('job-resumed', updatedJob);
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Reset a failed job for retry
|
|
173
|
+
*
|
|
174
|
+
* @param jobId - Job ID
|
|
175
|
+
* @throws Error if job not found
|
|
176
|
+
*/
|
|
177
|
+
resetJob(jobId) {
|
|
178
|
+
const job = this.getJobOrThrow(jobId);
|
|
179
|
+
const updatedJob = resetJob(job);
|
|
180
|
+
this.jobs.set(jobId, updatedJob);
|
|
181
|
+
this.logger.debug(`Job reset: ${jobId}`);
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Update job interval
|
|
185
|
+
*
|
|
186
|
+
* @param jobId - Job ID
|
|
187
|
+
* @param intervalMs - New interval in milliseconds
|
|
188
|
+
* @throws Error if job not found
|
|
189
|
+
*/
|
|
190
|
+
updateJobInterval(jobId, intervalMs) {
|
|
191
|
+
const job = this.getJobOrThrow(jobId);
|
|
192
|
+
const updatedJob = {
|
|
193
|
+
...job,
|
|
194
|
+
schedule: {
|
|
195
|
+
...job.schedule,
|
|
196
|
+
intervalMs,
|
|
197
|
+
},
|
|
198
|
+
};
|
|
199
|
+
this.jobs.set(jobId, updatedJob);
|
|
200
|
+
this.logger.debug(`Job interval updated: ${jobId} -> ${intervalMs}ms`);
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Load jobs from persisted state
|
|
204
|
+
*
|
|
205
|
+
* @param jobs - Array of persisted jobs
|
|
206
|
+
*/
|
|
207
|
+
loadJobs(jobs) {
|
|
208
|
+
this.jobs.clear();
|
|
209
|
+
for (const job of jobs) {
|
|
210
|
+
this.jobs.set(job.id, job);
|
|
211
|
+
}
|
|
212
|
+
this.logger.debug(`Loaded ${jobs.length} jobs from persistence`);
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Get all jobs for persistence
|
|
216
|
+
*
|
|
217
|
+
* @returns Array of all jobs
|
|
218
|
+
*/
|
|
219
|
+
getJobsForPersistence() {
|
|
220
|
+
return this.getAllJobs();
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Add an event listener
|
|
224
|
+
*
|
|
225
|
+
* @param listener - Callback function
|
|
226
|
+
*/
|
|
227
|
+
addEventListener(listener) {
|
|
228
|
+
this.listeners.add(listener);
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Remove an event listener
|
|
232
|
+
*
|
|
233
|
+
* @param listener - Callback function
|
|
234
|
+
*/
|
|
235
|
+
removeEventListener(listener) {
|
|
236
|
+
this.listeners.delete(listener);
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Get scheduler statistics
|
|
240
|
+
*
|
|
241
|
+
* @returns Scheduler stats
|
|
242
|
+
*/
|
|
243
|
+
getStats() {
|
|
244
|
+
const jobs = this.getAllJobs();
|
|
245
|
+
const byStatus = {};
|
|
246
|
+
const byType = {};
|
|
247
|
+
for (const job of jobs) {
|
|
248
|
+
byStatus[job.status] = (byStatus[job.status] || 0) + 1;
|
|
249
|
+
byType[job.type] = (byType[job.type] || 0) + 1;
|
|
250
|
+
}
|
|
251
|
+
return {
|
|
252
|
+
totalJobs: jobs.length,
|
|
253
|
+
byStatus,
|
|
254
|
+
byType,
|
|
255
|
+
dueCount: this.getNextDueJobs().length,
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Emit an event to all listeners
|
|
260
|
+
*/
|
|
261
|
+
emit(event, job, data) {
|
|
262
|
+
for (const listener of this.listeners) {
|
|
263
|
+
try {
|
|
264
|
+
listener(event, job, data);
|
|
265
|
+
}
|
|
266
|
+
catch (err) {
|
|
267
|
+
this.logger.error(`Error in job scheduler event listener: ${err}`);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Get a job or throw if not found
|
|
273
|
+
*/
|
|
274
|
+
getJobOrThrow(jobId) {
|
|
275
|
+
const job = this.jobs.get(jobId);
|
|
276
|
+
if (!job) {
|
|
277
|
+
throw new Error(`Job not found: ${jobId}`);
|
|
278
|
+
}
|
|
279
|
+
return job;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
//# sourceMappingURL=job-scheduler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"job-scheduler.js","sourceRoot":"","sources":["../../../../src/core/scheduler/job-scheduler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Schedule Persistence
|
|
3
|
+
*
|
|
4
|
+
* Persists job schedules to disk so they survive session restarts.
|
|
5
|
+
* Uses atomic writes to prevent corruption.
|
|
6
|
+
*
|
|
7
|
+
* @module core/scheduler/schedule-persistence
|
|
8
|
+
*/
|
|
9
|
+
import { ScheduledJob } from './scheduled-job.js';
|
|
10
|
+
import { Logger } from '../../utils/logger.js';
|
|
11
|
+
/**
|
|
12
|
+
* Schedule persistence options
|
|
13
|
+
*/
|
|
14
|
+
export interface SchedulePersistenceOptions {
|
|
15
|
+
/**
|
|
16
|
+
* Path to .specweave directory
|
|
17
|
+
* @default process.cwd() + '/.specweave'
|
|
18
|
+
*/
|
|
19
|
+
specweavePath?: string;
|
|
20
|
+
/**
|
|
21
|
+
* Logger instance
|
|
22
|
+
*/
|
|
23
|
+
logger?: Logger;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* SchedulePersistence - Saves and loads job schedules from disk
|
|
27
|
+
*
|
|
28
|
+
* Features:
|
|
29
|
+
* - Atomic writes using temp file + rename
|
|
30
|
+
* - Schema versioning for migration
|
|
31
|
+
* - Corruption recovery with defaults
|
|
32
|
+
*/
|
|
33
|
+
export declare class SchedulePersistence {
|
|
34
|
+
private readonly filePath;
|
|
35
|
+
private readonly logger;
|
|
36
|
+
constructor(options?: SchedulePersistenceOptions);
|
|
37
|
+
/**
|
|
38
|
+
* Load schedules from disk
|
|
39
|
+
*
|
|
40
|
+
* @returns Array of persisted jobs, empty array if file doesn't exist or is corrupted
|
|
41
|
+
*/
|
|
42
|
+
loadSchedules(): Promise<ScheduledJob[]>;
|
|
43
|
+
/**
|
|
44
|
+
* Save schedules to disk
|
|
45
|
+
*
|
|
46
|
+
* Uses atomic write (write to temp file, then rename) to prevent corruption.
|
|
47
|
+
*
|
|
48
|
+
* @param jobs - Jobs to persist
|
|
49
|
+
*/
|
|
50
|
+
saveSchedules(jobs: ScheduledJob[]): Promise<void>;
|
|
51
|
+
/**
|
|
52
|
+
* Update a single job in persistence
|
|
53
|
+
*
|
|
54
|
+
* @param jobId - Job ID to update
|
|
55
|
+
* @param updates - Partial job updates
|
|
56
|
+
*/
|
|
57
|
+
updateJob(jobId: string, updates: Partial<ScheduledJob>): Promise<void>;
|
|
58
|
+
/**
|
|
59
|
+
* Delete a job from persistence
|
|
60
|
+
*
|
|
61
|
+
* @param jobId - Job ID to delete
|
|
62
|
+
*/
|
|
63
|
+
deleteJob(jobId: string): Promise<void>;
|
|
64
|
+
/**
|
|
65
|
+
* Check if persistence file exists
|
|
66
|
+
*
|
|
67
|
+
* @returns true if file exists
|
|
68
|
+
*/
|
|
69
|
+
exists(): Promise<boolean>;
|
|
70
|
+
/**
|
|
71
|
+
* Get file path (for testing/debugging)
|
|
72
|
+
*/
|
|
73
|
+
getFilePath(): string;
|
|
74
|
+
/**
|
|
75
|
+
* Migrate schedules from older schema versions
|
|
76
|
+
*/
|
|
77
|
+
private migrateSchedules;
|
|
78
|
+
/**
|
|
79
|
+
* Backup corrupted file for debugging
|
|
80
|
+
*/
|
|
81
|
+
private backupCorruptedFile;
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=schedule-persistence.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schedule-persistence.d.ts","sourceRoot":"","sources":["../../../../src/core/scheduler/schedule-persistence.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,MAAM,EAAiB,MAAM,uBAAuB,CAAC;AA2B9D;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;GAOG;AACH,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;gBAEpB,OAAO,GAAE,0BAA+B;IAMpD;;;;OAIG;IACG,aAAa,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;IA4C9C;;;;;;OAMG;IACG,aAAa,CAAC,IAAI,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IA+BxD;;;;;OAKG;IACG,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAa7E;;;;OAIG;IACG,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAU7C;;;;OAIG;IACG,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC;IAShC;;OAEG;IACH,WAAW,IAAI,MAAM;IAIrB;;OAEG;YACW,gBAAgB;IAM9B;;OAEG;YACW,mBAAmB;CASlC"}
|