@gonzih/cc-agent 0.13.5 → 0.13.7
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/cron.d.ts +5 -1
- package/dist/cron.d.ts.map +1 -1
- package/dist/cron.js +113 -27
- package/dist/cron.js.map +1 -1
- package/package.json +1 -1
package/dist/cron.d.ts
CHANGED
|
@@ -22,16 +22,20 @@ export declare class CronEngine {
|
|
|
22
22
|
private namespace;
|
|
23
23
|
private running;
|
|
24
24
|
private tickTimer;
|
|
25
|
+
private readonly startupTime;
|
|
26
|
+
private readonly firedOnStartup;
|
|
25
27
|
constructor(manager: JobManager, namespace: string);
|
|
26
28
|
/** Crons Redis key for this namespace. */
|
|
27
29
|
private redisKey;
|
|
30
|
+
/** Tombstone set key — deleted cron ids, TTL 7 days. */
|
|
31
|
+
private deletedKey;
|
|
28
32
|
start(): Promise<void>;
|
|
29
33
|
stop(): Promise<void>;
|
|
30
34
|
private scheduleTick;
|
|
31
35
|
/** Called by tests to trigger a tick immediately without waiting. */
|
|
32
36
|
tick(): Promise<void>;
|
|
33
37
|
private fire;
|
|
34
|
-
/** Atomically
|
|
38
|
+
/** Atomically update lastFiredAt via Lua script — skips if cron was deleted concurrently. */
|
|
35
39
|
private updateLastFired;
|
|
36
40
|
listCrons(): Promise<CronJob[]>;
|
|
37
41
|
addCron(cron: Omit<CronJob, "id" | "createdAt">): Promise<CronJob>;
|
package/dist/cron.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cron.d.ts","sourceRoot":"","sources":["../src/cron.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAK7C,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;
|
|
1
|
+
{"version":3,"file":"cron.d.ts","sourceRoot":"","sources":["../src/cron.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAK7C,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AA2ED,qBAAa,UAAU;IAMT,OAAO,CAAC,OAAO;IAAc,OAAO,CAAC,SAAS;IAL1D,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,SAAS,CAA8C;IAC/D,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAc;IAC1C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAqB;gBAEhC,OAAO,EAAE,UAAU,EAAU,SAAS,EAAE,MAAM;IAElE,0CAA0C;IAC1C,OAAO,CAAC,QAAQ;IAIhB,wDAAwD;IACxD,OAAO,CAAC,UAAU;IAIZ,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAQtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAS3B,OAAO,CAAC,YAAY;IAYpB,qEAAqE;IAC/D,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;YAqBb,IAAI;IAkBlB,6FAA6F;YAC/E,eAAe;IAUvB,SAAS,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;IAiB/B,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,GAAG,WAAW,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC;IAclE,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAYxC,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;YAUlE,SAAS;YAUT,OAAO;CAuCtB"}
|
package/dist/cron.js
CHANGED
|
@@ -13,11 +13,80 @@ import { getRedis } from "./redis.js";
|
|
|
13
13
|
import { logger } from "./logger.js";
|
|
14
14
|
import { notify } from "./coordinator.js";
|
|
15
15
|
const TICK_INTERVAL_MS = 60_000; // 1 minute
|
|
16
|
+
// Lua script for atomic check-and-update of lastFiredAt.
|
|
17
|
+
// Returns 1 if updated, 0 if cron was not found (e.g. concurrently deleted).
|
|
18
|
+
const UPDATE_LAST_FIRED_LUA = `
|
|
19
|
+
local raw = redis.call('GET', KEYS[1])
|
|
20
|
+
if not raw then return 0 end
|
|
21
|
+
local crons = cjson.decode(raw)
|
|
22
|
+
for i, c in ipairs(crons) do
|
|
23
|
+
if c.id == ARGV[1] then
|
|
24
|
+
crons[i].lastFiredAt = ARGV[2]
|
|
25
|
+
redis.call('SET', KEYS[1], cjson.encode(crons))
|
|
26
|
+
return 1
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
return 0
|
|
30
|
+
`;
|
|
31
|
+
// Lua script for atomic deletion of a cron by id.
|
|
32
|
+
// Returns 1 if found and removed, 0 if not found.
|
|
33
|
+
const DELETE_CRON_LUA = `
|
|
34
|
+
local raw = redis.call('GET', KEYS[1])
|
|
35
|
+
if not raw then return 0 end
|
|
36
|
+
local crons = cjson.decode(raw)
|
|
37
|
+
local new = {}
|
|
38
|
+
local found = 0
|
|
39
|
+
for _, c in ipairs(crons) do
|
|
40
|
+
if c.id == ARGV[1] then
|
|
41
|
+
found = 1
|
|
42
|
+
else
|
|
43
|
+
table.insert(new, c)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
if found == 1 then
|
|
47
|
+
redis.call('SET', KEYS[1], cjson.encode(new))
|
|
48
|
+
end
|
|
49
|
+
return found
|
|
50
|
+
`;
|
|
51
|
+
// Lua script for atomic addition of a cron (skips if id already exists).
|
|
52
|
+
// Returns 1 if added, 0 if duplicate.
|
|
53
|
+
const ADD_CRON_LUA = `
|
|
54
|
+
local raw = redis.call('GET', KEYS[1])
|
|
55
|
+
local crons = raw and cjson.decode(raw) or {}
|
|
56
|
+
local newCron = cjson.decode(ARGV[1])
|
|
57
|
+
for _, c in ipairs(crons) do
|
|
58
|
+
if c.id == newCron.id then return 0 end
|
|
59
|
+
end
|
|
60
|
+
table.insert(crons, newCron)
|
|
61
|
+
redis.call('SET', KEYS[1], cjson.encode(crons))
|
|
62
|
+
return 1
|
|
63
|
+
`;
|
|
64
|
+
// Lua script for atomic update of a cron's fields.
|
|
65
|
+
// ARGV[1] = id, ARGV[2] = JSON of partial updates.
|
|
66
|
+
// Returns 1 if updated, 0 if not found.
|
|
67
|
+
const UPDATE_CRON_LUA = `
|
|
68
|
+
local raw = redis.call('GET', KEYS[1])
|
|
69
|
+
if not raw then return 0 end
|
|
70
|
+
local crons = cjson.decode(raw)
|
|
71
|
+
local updates = cjson.decode(ARGV[2])
|
|
72
|
+
for i, c in ipairs(crons) do
|
|
73
|
+
if c.id == ARGV[1] then
|
|
74
|
+
for k, v in pairs(updates) do
|
|
75
|
+
crons[i][k] = v
|
|
76
|
+
end
|
|
77
|
+
redis.call('SET', KEYS[1], cjson.encode(crons))
|
|
78
|
+
return 1
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
return 0
|
|
82
|
+
`;
|
|
16
83
|
export class CronEngine {
|
|
17
84
|
manager;
|
|
18
85
|
namespace;
|
|
19
86
|
running = false;
|
|
20
87
|
tickTimer = null;
|
|
88
|
+
startupTime = Date.now();
|
|
89
|
+
firedOnStartup = new Set();
|
|
21
90
|
constructor(manager, namespace) {
|
|
22
91
|
this.manager = manager;
|
|
23
92
|
this.namespace = namespace;
|
|
@@ -26,6 +95,10 @@ export class CronEngine {
|
|
|
26
95
|
redisKey() {
|
|
27
96
|
return `cca:crons:${this.namespace}`;
|
|
28
97
|
}
|
|
98
|
+
/** Tombstone set key — deleted cron ids, TTL 7 days. */
|
|
99
|
+
deletedKey() {
|
|
100
|
+
return `cca:deleted-crons:${this.namespace}`;
|
|
101
|
+
}
|
|
29
102
|
async start() {
|
|
30
103
|
if (this.running)
|
|
31
104
|
return;
|
|
@@ -58,12 +131,21 @@ export class CronEngine {
|
|
|
58
131
|
async tick() {
|
|
59
132
|
const crons = await this.listCrons();
|
|
60
133
|
const now = Date.now();
|
|
134
|
+
const isFirstTick = now - this.startupTime < TICK_INTERVAL_MS * 2;
|
|
61
135
|
for (const cron of crons) {
|
|
62
136
|
if (cron.enabled === false)
|
|
63
137
|
continue;
|
|
64
138
|
const lastFired = cron.lastFiredAt ? new Date(cron.lastFiredAt).getTime() : 0;
|
|
65
139
|
if (now - lastFired >= cron.intervalMs) {
|
|
66
|
-
|
|
140
|
+
if (isFirstTick && !this.firedOnStartup.has(cron.id)) {
|
|
141
|
+
// Spread startup fires: stagger by index * 30s to avoid thundering herd
|
|
142
|
+
const idx = crons.indexOf(cron);
|
|
143
|
+
setTimeout(() => this.fire(cron).catch(() => { }), idx * 30_000);
|
|
144
|
+
this.firedOnStartup.add(cron.id);
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
await this.fire(cron);
|
|
148
|
+
}
|
|
67
149
|
}
|
|
68
150
|
}
|
|
69
151
|
}
|
|
@@ -85,18 +167,12 @@ export class CronEngine {
|
|
|
85
167
|
logger.warn("cron:fire-failed", { id: cron.id, err: String(err) });
|
|
86
168
|
}
|
|
87
169
|
}
|
|
88
|
-
/** Atomically
|
|
170
|
+
/** Atomically update lastFiredAt via Lua script — skips if cron was deleted concurrently. */
|
|
89
171
|
async updateLastFired(id) {
|
|
90
172
|
const redis = getRedis();
|
|
91
173
|
if (!redis)
|
|
92
174
|
return;
|
|
93
|
-
|
|
94
|
-
const crons = raw ? JSON.parse(raw) : [];
|
|
95
|
-
const idx = crons.findIndex((c) => c.id === id);
|
|
96
|
-
if (idx === -1)
|
|
97
|
-
return; // was deleted — don't re-add
|
|
98
|
-
crons[idx].lastFiredAt = new Date().toISOString();
|
|
99
|
-
await redis.set(this.redisKey(), JSON.stringify(crons));
|
|
175
|
+
await redis.eval(UPDATE_LAST_FIRED_LUA, 1, this.redisKey(), id, new Date().toISOString());
|
|
100
176
|
}
|
|
101
177
|
// ---------------------------------------------------------------------------
|
|
102
178
|
// CRUD
|
|
@@ -105,46 +181,56 @@ export class CronEngine {
|
|
|
105
181
|
const redis = getRedis();
|
|
106
182
|
if (!redis)
|
|
107
183
|
return [];
|
|
108
|
-
const raw = await
|
|
184
|
+
const [raw, deletedMembers] = await Promise.all([
|
|
185
|
+
redis.get(this.redisKey()),
|
|
186
|
+
redis.smembers(this.deletedKey()),
|
|
187
|
+
]);
|
|
109
188
|
if (!raw)
|
|
110
189
|
return [];
|
|
111
190
|
try {
|
|
112
|
-
|
|
191
|
+
const deletedSet = new Set(deletedMembers);
|
|
192
|
+
const all = JSON.parse(raw);
|
|
193
|
+
return all.filter((c) => !deletedSet.has(c.id));
|
|
113
194
|
}
|
|
114
195
|
catch {
|
|
115
196
|
return [];
|
|
116
197
|
}
|
|
117
198
|
}
|
|
118
199
|
async addCron(cron) {
|
|
200
|
+
const redis = getRedis();
|
|
119
201
|
const newCron = {
|
|
120
202
|
...cron,
|
|
121
203
|
id: uuidv4(),
|
|
122
204
|
createdAt: new Date().toISOString(),
|
|
123
205
|
};
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
206
|
+
if (redis) {
|
|
207
|
+
await redis.eval(ADD_CRON_LUA, 1, this.redisKey(), JSON.stringify(newCron));
|
|
208
|
+
}
|
|
127
209
|
logger.info("cron:added", { id: newCron.id, schedule: newCron.schedule });
|
|
128
210
|
return newCron;
|
|
129
211
|
}
|
|
130
212
|
async deleteCron(id) {
|
|
131
|
-
const
|
|
132
|
-
|
|
133
|
-
if (idx === -1)
|
|
213
|
+
const redis = getRedis();
|
|
214
|
+
if (!redis)
|
|
134
215
|
return false;
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
216
|
+
const found = await redis.eval(DELETE_CRON_LUA, 1, this.redisKey(), id);
|
|
217
|
+
if (found === 1) {
|
|
218
|
+
await redis.sadd(this.deletedKey(), id);
|
|
219
|
+
await redis.expire(this.deletedKey(), 7 * 24 * 3600);
|
|
220
|
+
logger.info("cron:deleted", { id });
|
|
221
|
+
}
|
|
222
|
+
return found === 1;
|
|
139
223
|
}
|
|
140
224
|
async updateCron(id, updates) {
|
|
141
|
-
const
|
|
142
|
-
|
|
143
|
-
if (idx === -1)
|
|
225
|
+
const redis = getRedis();
|
|
226
|
+
if (!redis)
|
|
144
227
|
return null;
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
228
|
+
const found = await redis.eval(UPDATE_CRON_LUA, 1, this.redisKey(), id, JSON.stringify(updates));
|
|
229
|
+
if (!found)
|
|
230
|
+
return null;
|
|
231
|
+
// Read back the merged cron — we need the full object as the return value
|
|
232
|
+
const crons = await this.listCrons();
|
|
233
|
+
return crons.find((c) => c.id === id) ?? null;
|
|
148
234
|
}
|
|
149
235
|
async saveCrons(crons) {
|
|
150
236
|
const redis = getRedis();
|
package/dist/cron.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cron.js","sourceRoot":"","sources":["../src/cron.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAChC,OAAO,EAAU,QAAQ,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,EAAE,IAAI,MAAM,EAAE,MAAM,MAAM,CAAC;AAEpC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAc1C,MAAM,gBAAgB,GAAG,MAAM,CAAC,CAAC,WAAW;AAE5C,MAAM,OAAO,UAAU;
|
|
1
|
+
{"version":3,"file":"cron.js","sourceRoot":"","sources":["../src/cron.ts"],"names":[],"mappings":"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"}
|