amalgm 0.1.49 → 0.1.50
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/package.json +1 -1
- package/runtime/scripts/amalgm-mcp/config.js +1 -1
- package/runtime/scripts/amalgm-mcp/events/executor.js +31 -0
- package/runtime/scripts/amalgm-mcp/events/store.js +202 -2
- package/runtime/scripts/amalgm-mcp/fs/rest.js +348 -16
- package/runtime/scripts/amalgm-mcp/mcp-connections/rest.js +26 -5
- package/runtime/scripts/amalgm-mcp/server/http.js +2 -1
- package/runtime/scripts/amalgm-mcp/state/db.js +72 -0
- package/runtime/scripts/amalgm-mcp/state/snapshot.js +12 -1
- package/runtime/scripts/amalgm-mcp/tasks/executor.js +13 -4
- package/runtime/scripts/amalgm-mcp/tasks/scheduler.js +60 -22
- package/runtime/scripts/amalgm-mcp/tasks/store.js +783 -55
- package/runtime/scripts/amalgm-mcp/tasks/tools.js +12 -4
- package/runtime/scripts/amalgm-mcp/tests/tasks-store.test.js +113 -0
- package/runtime/scripts/local-gateway.js +13 -0
|
@@ -1,18 +1,27 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Task scheduler —
|
|
2
|
+
* Task scheduler — 60s poll loop.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Claims due rows from SQLite, then kicks off execution via tasks/executor.js.
|
|
5
|
+
* The SQLite task_runs table is the durable receipt/claim log; executor.js
|
|
6
|
+
* keeps only abort controllers for live in-process cancellation.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
const { SCHEDULER_INTERVAL_MS } = require('../config');
|
|
10
|
-
const {
|
|
10
|
+
const { claimDueTaskRuns, expireStaleTaskRuns } = require('./store');
|
|
11
11
|
const { executeTask, isRunning } = require('./executor');
|
|
12
12
|
const { loadCronParser } = require('../deps');
|
|
13
13
|
|
|
14
14
|
let schedulerTimer = null;
|
|
15
15
|
let _cronParser = null;
|
|
16
|
+
let isPolling = false;
|
|
17
|
+
|
|
18
|
+
const schedulerStatus = {
|
|
19
|
+
startedAt: null,
|
|
20
|
+
lastTickAt: null,
|
|
21
|
+
lastError: null,
|
|
22
|
+
lastClaimed: 0,
|
|
23
|
+
lastExpired: 0,
|
|
24
|
+
};
|
|
16
25
|
|
|
17
26
|
function cron() {
|
|
18
27
|
if (!_cronParser) _cronParser = loadCronParser();
|
|
@@ -79,23 +88,45 @@ function isTaskDue(task, now) {
|
|
|
79
88
|
|
|
80
89
|
function startScheduler() {
|
|
81
90
|
console.log(`[AmalgmMCP:Scheduler] Starting (interval: ${SCHEDULER_INTERVAL_MS}ms)`);
|
|
82
|
-
schedulerTimer
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
91
|
+
if (schedulerTimer) clearInterval(schedulerTimer);
|
|
92
|
+
schedulerStatus.startedAt = new Date().toISOString();
|
|
93
|
+
pollScheduler();
|
|
94
|
+
schedulerTimer = setInterval(pollScheduler, SCHEDULER_INTERVAL_MS);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function pollScheduler() {
|
|
98
|
+
if (isPolling) return;
|
|
99
|
+
isPolling = true;
|
|
100
|
+
try {
|
|
101
|
+
const now = new Date();
|
|
102
|
+
schedulerStatus.lastTickAt = now.toISOString();
|
|
103
|
+
schedulerStatus.lastExpired = expireStaleTaskRuns(now, { source: 'scheduler:expire' });
|
|
104
|
+
const claims = claimDueTaskRuns(now, { source: 'scheduler' });
|
|
105
|
+
schedulerStatus.lastClaimed = claims.length;
|
|
106
|
+
schedulerStatus.lastError = null;
|
|
107
|
+
|
|
108
|
+
for (const claim of claims) {
|
|
109
|
+
if (!claim?.task || !claim?.run) continue;
|
|
110
|
+
if (isRunning(claim.task.id)) continue;
|
|
111
|
+
executeTask(claim.task, claim.run).catch((err) => {
|
|
112
|
+
console.error(`[AmalgmMCP:Scheduler] Task ${claim.task.id} error:`, err.message);
|
|
113
|
+
});
|
|
97
114
|
}
|
|
98
|
-
}
|
|
115
|
+
} catch (err) {
|
|
116
|
+
schedulerStatus.lastError = err.message;
|
|
117
|
+
console.error('[AmalgmMCP:Scheduler] Poll error:', err.message);
|
|
118
|
+
} finally {
|
|
119
|
+
isPolling = false;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function getSchedulerStatus() {
|
|
124
|
+
return {
|
|
125
|
+
intervalMs: SCHEDULER_INTERVAL_MS,
|
|
126
|
+
running: Boolean(schedulerTimer),
|
|
127
|
+
polling: isPolling,
|
|
128
|
+
...schedulerStatus,
|
|
129
|
+
};
|
|
99
130
|
}
|
|
100
131
|
|
|
101
132
|
function stopScheduler() {
|
|
@@ -105,4 +136,11 @@ function stopScheduler() {
|
|
|
105
136
|
}
|
|
106
137
|
}
|
|
107
138
|
|
|
108
|
-
module.exports = {
|
|
139
|
+
module.exports = {
|
|
140
|
+
getSchedulerStatus,
|
|
141
|
+
isTaskDue,
|
|
142
|
+
pollScheduler,
|
|
143
|
+
startScheduler,
|
|
144
|
+
stopScheduler,
|
|
145
|
+
validateCronExpr,
|
|
146
|
+
};
|