@cat-factory/node-server 0.92.7 → 0.92.9
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/environments.d.ts +3 -3
- package/dist/environments.d.ts.map +1 -1
- package/dist/environments.js +12 -14
- package/dist/environments.js.map +1 -1
- package/dist/githubReconcile.d.ts +4 -19
- package/dist/githubReconcile.d.ts.map +1 -1
- package/dist/githubReconcile.js +18 -103
- package/dist/githubReconcile.js.map +1 -1
- package/dist/initiativeLoop.d.ts +4 -2
- package/dist/initiativeLoop.d.ts.map +1 -1
- package/dist/initiativeLoop.js +13 -13
- package/dist/initiativeLoop.js.map +1 -1
- package/dist/kaizen.d.ts +3 -3
- package/dist/kaizen.d.ts.map +1 -1
- package/dist/kaizen.js +12 -23
- package/dist/kaizen.js.map +1 -1
- package/dist/notifications.d.ts +3 -3
- package/dist/notifications.d.ts.map +1 -1
- package/dist/notifications.js +12 -14
- package/dist/notifications.js.map +1 -1
- package/dist/recurring.d.ts +3 -3
- package/dist/recurring.d.ts.map +1 -1
- package/dist/recurring.js +12 -14
- package/dist/recurring.js.map +1 -1
- package/dist/retention.d.ts.map +1 -1
- package/dist/retention.js +17 -22
- package/dist/retention.js.map +1 -1
- package/dist/sweeper.d.ts +24 -0
- package/dist/sweeper.d.ts.map +1 -0
- package/dist/sweeper.js +23 -0
- package/dist/sweeper.js.map +1 -0
- package/package.json +20 -19
package/dist/environments.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { Clock } from '@cat-factory/kernel';
|
|
2
2
|
import type { Logger, ServerContainer } from '@cat-factory/server';
|
|
3
3
|
/**
|
|
4
|
-
* Start the periodic environment TTL sweep. Runs once immediately then on
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Start the periodic environment TTL sweep. Runs once immediately then on the interval,
|
|
5
|
+
* non-overlapping + best-effort (see {@link startSweeper}). Returns a stop function that
|
|
6
|
+
* clears the timer.
|
|
7
7
|
*/
|
|
8
8
|
export declare function startEnvironmentSweeper(container: ServerContainer, clock: Clock, log: Logger): () => void;
|
|
9
9
|
//# sourceMappingURL=environments.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"environments.d.ts","sourceRoot":"","sources":["../src/environments.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAA;AAChD,OAAO,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"environments.d.ts","sourceRoot":"","sources":["../src/environments.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAA;AAChD,OAAO,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAWlE;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,eAAe,EAC1B,KAAK,EAAE,KAAK,EACZ,GAAG,EAAE,MAAM,GACV,MAAM,IAAI,CAaZ"}
|
package/dist/environments.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { startSweeper } from './sweeper.js';
|
|
1
2
|
// Periodic ephemeral-environment TTL teardown for the Node facade — the analogue of
|
|
2
3
|
// the Worker's every-2-min cron call to `sweepExpiredEnvironments`. The Node service
|
|
3
4
|
// has no cron, so a timer destroys environments whose expiry has elapsed. No-op when
|
|
@@ -5,27 +6,24 @@
|
|
|
5
6
|
/** How often the Node service tears down expired environments. */
|
|
6
7
|
const ENVIRONMENT_SWEEP_INTERVAL_MS = 2 * 60 * 1000;
|
|
7
8
|
/**
|
|
8
|
-
* Start the periodic environment TTL sweep. Runs once immediately then on
|
|
9
|
-
*
|
|
10
|
-
*
|
|
9
|
+
* Start the periodic environment TTL sweep. Runs once immediately then on the interval,
|
|
10
|
+
* non-overlapping + best-effort (see {@link startSweeper}). Returns a stop function that
|
|
11
|
+
* clears the timer.
|
|
11
12
|
*/
|
|
12
13
|
export function startEnvironmentSweeper(container, clock, log) {
|
|
13
14
|
const environments = container.environments;
|
|
14
15
|
if (!environments)
|
|
15
16
|
return () => { };
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
return startSweeper({
|
|
18
|
+
name: 'environment-ttl',
|
|
19
|
+
intervalMs: ENVIRONMENT_SWEEP_INTERVAL_MS,
|
|
20
|
+
log,
|
|
21
|
+
failureMessage: 'environment TTL sweep failed',
|
|
22
|
+
tick: async () => {
|
|
18
23
|
const torn = await environments.teardownService.sweepExpired(clock.now());
|
|
19
24
|
if (torn > 0)
|
|
20
25
|
log.info({ torn }, 'tore down expired environments');
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
log.error({ err: error instanceof Error ? error.message : String(error) }, 'environment TTL sweep failed');
|
|
24
|
-
}
|
|
25
|
-
};
|
|
26
|
-
void tick();
|
|
27
|
-
const timer = setInterval(() => void tick(), ENVIRONMENT_SWEEP_INTERVAL_MS);
|
|
28
|
-
timer.unref?.();
|
|
29
|
-
return () => clearInterval(timer);
|
|
26
|
+
},
|
|
27
|
+
});
|
|
30
28
|
}
|
|
31
29
|
//# sourceMappingURL=environments.js.map
|
package/dist/environments.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"environments.js","sourceRoot":"","sources":["../src/environments.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"environments.js","sourceRoot":"","sources":["../src/environments.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAE3C,oFAAoF;AACpF,qFAAqF;AACrF,qFAAqF;AACrF,yFAAyF;AAEzF,kEAAkE;AAClE,MAAM,6BAA6B,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAA;AAEnD;;;;GAIG;AACH,MAAM,UAAU,uBAAuB,CACrC,SAA0B,EAC1B,KAAY,EACZ,GAAW;IAEX,MAAM,YAAY,GAAG,SAAS,CAAC,YAAY,CAAA;IAC3C,IAAI,CAAC,YAAY;QAAE,OAAO,GAAG,EAAE,GAAE,CAAC,CAAA;IAClC,OAAO,YAAY,CAAC;QAClB,IAAI,EAAE,iBAAiB;QACvB,UAAU,EAAE,6BAA6B;QACzC,GAAG;QACH,cAAc,EAAE,8BAA8B;QAC9C,IAAI,EAAE,KAAK,IAAI,EAAE;YACf,MAAM,IAAI,GAAG,MAAM,YAAY,CAAC,eAAe,CAAC,YAAY,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAA;YACzE,IAAI,IAAI,GAAG,CAAC;gBAAE,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,gCAAgC,CAAC,CAAA;QACpE,CAAC;KACF,CAAC,CAAA;AACJ,CAAC"}
|
|
@@ -1,24 +1,9 @@
|
|
|
1
|
-
import type { Clock
|
|
2
|
-
import type
|
|
3
|
-
/** A projection not synced for this long is considered stale (matches the Worker). */
|
|
4
|
-
export declare const GITHUB_RECONCILE_STALE_MS: number;
|
|
5
|
-
/** The seams the reconcile pass drives (kept narrow so it is unit-testable with fakes). */
|
|
6
|
-
export interface GitHubReconcileDeps {
|
|
7
|
-
repoProjectionRepository: Pick<RepoProjectionRepository, 'listStale'>;
|
|
8
|
-
installationRepository: Pick<GitHubInstallationRepository, 'softDelete'>;
|
|
9
|
-
/** The GitHub module's incremental per-repo resync (`GitHubSyncService.syncRepoById`). */
|
|
10
|
-
syncRepoById: (workspaceId: string, repoGithubId: number) => Promise<void>;
|
|
11
|
-
}
|
|
12
|
-
/**
|
|
13
|
-
* One reconcile pass: re-sync every stale repo projection, tombstoning installations
|
|
14
|
-
* that are gone. Best-effort per repo — one failure must not abort the rest. Returns
|
|
15
|
-
* the number of repos successfully re-synced.
|
|
16
|
-
*/
|
|
17
|
-
export declare function reconcileStaleRepos(deps: GitHubReconcileDeps, clock: Clock, staleMs: number, log: Logger): Promise<number>;
|
|
1
|
+
import type { Clock } from '@cat-factory/kernel';
|
|
2
|
+
import { type GitHubReconcileDeps, type Logger } from '@cat-factory/server';
|
|
18
3
|
/**
|
|
19
4
|
* Start the periodic reconcile sweep. Runs once immediately then on the two-minute
|
|
20
|
-
* timer
|
|
21
|
-
*
|
|
5
|
+
* timer, non-overlapping + best-effort (see {@link startSweeper}). Returns a stop
|
|
6
|
+
* function that clears the timer.
|
|
22
7
|
*/
|
|
23
8
|
export declare function startGitHubReconcileSweeper(deps: GitHubReconcileDeps, clock: Clock, log: Logger): () => void;
|
|
24
9
|
//# sourceMappingURL=githubReconcile.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"githubReconcile.d.ts","sourceRoot":"","sources":["../src/githubReconcile.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"githubReconcile.d.ts","sourceRoot":"","sources":["../src/githubReconcile.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAA;AAChD,OAAO,EAEL,KAAK,mBAAmB,EACxB,KAAK,MAAM,EAEZ,MAAM,qBAAqB,CAAA;AAc5B;;;;GAIG;AACH,wBAAgB,2BAA2B,CACzC,IAAI,EAAE,mBAAmB,EACzB,KAAK,EAAE,KAAK,EACZ,GAAG,EAAE,MAAM,GACV,MAAM,IAAI,CAWZ"}
|
package/dist/githubReconcile.js
CHANGED
|
@@ -1,115 +1,30 @@
|
|
|
1
|
+
import { GITHUB_RECONCILE_STALE_MS, reconcileStaleRepos, } from '@cat-factory/server';
|
|
2
|
+
import { startSweeper } from './sweeper.js';
|
|
1
3
|
// Periodic GitHub reconciliation for the Node facade — the analogue of the Worker's
|
|
2
|
-
// every-2-min `github-reconcile` cron
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
// The Worker enqueues resyncs when a queue is bound; Node has no queue, so it uses
|
|
9
|
-
// the Worker's direct-sync fallback path (`syncService.syncRepoById`) inline.
|
|
4
|
+
// every-2-min `github-reconcile` cron. Webhooks are the primary sync path but can be
|
|
5
|
+
// missed (a delivery outage, a restart mid-delivery), so this backstop re-syncs every
|
|
6
|
+
// tracked repo whose projection has gone stale. The reconcile pass itself lives in the
|
|
7
|
+
// shared `@cat-factory/server` `reconcileStaleRepos` (so it can't drift from the Worker);
|
|
8
|
+
// this file supplies only the Node driver — a direct inline resync (Node has no queue).
|
|
9
|
+
// The pass itself is unit-tested in `@cat-factory/server` (one test for one implementation).
|
|
10
10
|
/** How often the reconcile pass runs (matches the Worker's frequent cron). */
|
|
11
11
|
const GITHUB_RECONCILE_INTERVAL_MS = 2 * 60 * 1000;
|
|
12
|
-
/** A projection not synced for this long is considered stale (matches the Worker). */
|
|
13
|
-
export const GITHUB_RECONCILE_STALE_MS = 30 * 60 * 1000;
|
|
14
|
-
/**
|
|
15
|
-
* One reconcile pass: re-sync every stale repo projection, tombstoning installations
|
|
16
|
-
* that are gone. Best-effort per repo — one failure must not abort the rest. Returns
|
|
17
|
-
* the number of repos successfully re-synced.
|
|
18
|
-
*/
|
|
19
|
-
export async function reconcileStaleRepos(deps, clock, staleMs, log) {
|
|
20
|
-
// `listStale` already excludes repos whose installation is tombstoned, so a dead
|
|
21
|
-
// installation stops being swept once it is known-gone; the handling below tombstones
|
|
22
|
-
// one the webhook never told us about (a missed uninstall), so it stops next pass.
|
|
23
|
-
const stale = await deps.repoProjectionRepository.listStale(clock.now() - staleMs);
|
|
24
|
-
let synced = 0;
|
|
25
|
-
for (const repo of stale) {
|
|
26
|
-
try {
|
|
27
|
-
await deps.syncRepoById(repo.workspaceId, repo.githubId);
|
|
28
|
-
synced += 1;
|
|
29
|
-
}
|
|
30
|
-
catch (error) {
|
|
31
|
-
// Best-effort pass (webhooks are the primary path): a gone/forbidden GitHub App
|
|
32
|
-
// installation (uninstalled or revoked → 401/404 when minting its token) is an
|
|
33
|
-
// expected operational state for a stale projection, so log it at warn; any
|
|
34
|
-
// other fault is a real error. Either way, continue with the next repo.
|
|
35
|
-
const gone = isInstallationGoneError(error);
|
|
36
|
-
// A token-mint 404/410 means the installation itself is gone — uninstalled or
|
|
37
|
-
// revoked without us receiving the webhook. Tombstone it so this and every future
|
|
38
|
-
// pass skip ALL its repos until it is reinstalled (the `unsuspend`/reinstall
|
|
39
|
-
// webhook clears the tombstone). Scoped to the mint error (not a repo-level 404,
|
|
40
|
-
// which means a single deleted repo) and to 404/410 (never 401, which can be a
|
|
41
|
-
// transient app-JWT fault hitting everything).
|
|
42
|
-
if (isInstallationTokenGoneError(error)) {
|
|
43
|
-
try {
|
|
44
|
-
await deps.installationRepository.softDelete(repo.installationId, clock.now());
|
|
45
|
-
}
|
|
46
|
-
catch {
|
|
47
|
-
// Best-effort: a failed tombstone just means we retry (and warn) next pass.
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
log[gone ? 'warn' : 'error']({
|
|
51
|
-
sweeper: 'github-reconcile',
|
|
52
|
-
workspaceId: repo.workspaceId,
|
|
53
|
-
repoGithubId: repo.githubId,
|
|
54
|
-
installationId: repo.installationId,
|
|
55
|
-
err: error instanceof Error ? error.message : String(error),
|
|
56
|
-
}, gone
|
|
57
|
-
? 'skipping stale repo whose GitHub App installation is gone (uninstalled/revoked); reinstall the app to re-enable it'
|
|
58
|
-
: 'repo resync failed');
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
return synced;
|
|
62
|
-
}
|
|
63
12
|
/**
|
|
64
13
|
* Start the periodic reconcile sweep. Runs once immediately then on the two-minute
|
|
65
|
-
* timer
|
|
66
|
-
*
|
|
14
|
+
* timer, non-overlapping + best-effort (see {@link startSweeper}). Returns a stop
|
|
15
|
+
* function that clears the timer.
|
|
67
16
|
*/
|
|
68
17
|
export function startGitHubReconcileSweeper(deps, clock, log) {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
running = true;
|
|
76
|
-
try {
|
|
18
|
+
return startSweeper({
|
|
19
|
+
name: 'github-reconcile',
|
|
20
|
+
intervalMs: GITHUB_RECONCILE_INTERVAL_MS,
|
|
21
|
+
log,
|
|
22
|
+
failureMessage: 'github reconcile sweep failed',
|
|
23
|
+
tick: async () => {
|
|
77
24
|
const synced = await reconcileStaleRepos(deps, clock, GITHUB_RECONCILE_STALE_MS, log);
|
|
78
25
|
if (synced > 0)
|
|
79
26
|
log.info({ synced }, 'reconciled stale github repo projections');
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
log.error({ err: error instanceof Error ? error.message : String(error) }, 'github reconcile sweep failed');
|
|
83
|
-
}
|
|
84
|
-
finally {
|
|
85
|
-
running = false;
|
|
86
|
-
}
|
|
87
|
-
};
|
|
88
|
-
void tick();
|
|
89
|
-
const timer = setInterval(() => void tick(), GITHUB_RECONCILE_INTERVAL_MS);
|
|
90
|
-
timer.unref?.();
|
|
91
|
-
return () => clearInterval(timer);
|
|
92
|
-
}
|
|
93
|
-
/**
|
|
94
|
-
* Whether a sync error is a *gone/forbidden GitHub App installation* rather than a
|
|
95
|
-
* transient fault: minting an installation token for an uninstalled or revoked
|
|
96
|
-
* installation returns 401/404 (and a deleted repo 404/410). These are not worth
|
|
97
|
-
* an error-level log or a retry storm — the connection needs human action.
|
|
98
|
-
* (Mirrors the Worker's `sync-consumer.ts` classification.)
|
|
99
|
-
*/
|
|
100
|
-
function isInstallationGoneError(error) {
|
|
101
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
102
|
-
return /\(HTTP (401|404|410)\)/.test(message);
|
|
103
|
-
}
|
|
104
|
-
/**
|
|
105
|
-
* Whether the error is specifically a *token mint* returning 404/410 — i.e. the
|
|
106
|
-
* installation itself is gone (uninstalled/revoked), not merely a single repo
|
|
107
|
-
* being inaccessible. Matches the App registry's mint-failure message. Excludes 401
|
|
108
|
-
* (a transient app-JWT/clock fault would mint-fail for every installation, and must
|
|
109
|
-
* not tombstone a healthy connection).
|
|
110
|
-
*/
|
|
111
|
-
function isInstallationTokenGoneError(error) {
|
|
112
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
113
|
-
return /Failed to mint installation token .*\(HTTP (404|410)\)/i.test(message);
|
|
27
|
+
},
|
|
28
|
+
});
|
|
114
29
|
}
|
|
115
30
|
//# sourceMappingURL=githubReconcile.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"githubReconcile.js","sourceRoot":"","sources":["../src/githubReconcile.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"githubReconcile.js","sourceRoot":"","sources":["../src/githubReconcile.ts"],"names":[],"mappings":"AACA,OAAO,EACL,yBAAyB,EAGzB,mBAAmB,GACpB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAE3C,oFAAoF;AACpF,qFAAqF;AACrF,sFAAsF;AACtF,uFAAuF;AACvF,0FAA0F;AAC1F,wFAAwF;AACxF,6FAA6F;AAE7F,8EAA8E;AAC9E,MAAM,4BAA4B,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAA;AAElD;;;;GAIG;AACH,MAAM,UAAU,2BAA2B,CACzC,IAAyB,EACzB,KAAY,EACZ,GAAW;IAEX,OAAO,YAAY,CAAC;QAClB,IAAI,EAAE,kBAAkB;QACxB,UAAU,EAAE,4BAA4B;QACxC,GAAG;QACH,cAAc,EAAE,+BAA+B;QAC/C,IAAI,EAAE,KAAK,IAAI,EAAE;YACf,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC,IAAI,EAAE,KAAK,EAAE,yBAAyB,EAAE,GAAG,CAAC,CAAA;YACrF,IAAI,MAAM,GAAG,CAAC;gBAAE,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,EAAE,0CAA0C,CAAC,CAAA;QAClF,CAAC;KACF,CAAC,CAAA;AACJ,CAAC"}
|
package/dist/initiativeLoop.d.ts
CHANGED
|
@@ -15,8 +15,10 @@ import type { Logger, ServerContainer } from '@cat-factory/server';
|
|
|
15
15
|
export declare function resolveSweepInterval(env?: NodeJS.ProcessEnv): number;
|
|
16
16
|
/**
|
|
17
17
|
* Start the periodic initiative-loop sweep. Runs once immediately then on the resolved interval
|
|
18
|
-
* (default one minute; see {@link resolveSweepInterval})
|
|
19
|
-
*
|
|
18
|
+
* (default one minute; see {@link resolveSweepInterval}), non-overlapping + best-effort (see
|
|
19
|
+
* {@link startSweeper}). The non-overlap guard matters most here: `runDue` reconciles spawned
|
|
20
|
+
* tasks and spawns the next wave, so two concurrent passes could both observe "no active run"
|
|
21
|
+
* and double-spawn. Returns a stop function that clears the timer.
|
|
20
22
|
*/
|
|
21
23
|
export declare function startInitiativeLoopSweeper(container: ServerContainer, clock: Clock, log: Logger, intervalMs?: number): () => void;
|
|
22
24
|
//# sourceMappingURL=initiativeLoop.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"initiativeLoop.d.ts","sourceRoot":"","sources":["../src/initiativeLoop.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAA;AAChD,OAAO,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"initiativeLoop.d.ts","sourceRoot":"","sources":["../src/initiativeLoop.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAA;AAChD,OAAO,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAYlE;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAIjF;AAED;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CACxC,SAAS,EAAE,eAAe,EAC1B,KAAK,EAAE,KAAK,EACZ,GAAG,EAAE,MAAM,EACX,UAAU,GAAE,MAA+B,GAC1C,MAAM,IAAI,CAeZ"}
|
package/dist/initiativeLoop.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { startSweeper } from './sweeper.js';
|
|
1
2
|
// Periodic initiative-execution-loop sweep for the Node facade — the analogue of the Worker's
|
|
2
3
|
// every-2-min cron call to `initiatives.loop.runDue`. The Node service has no cron, so a timer
|
|
3
4
|
// ticks every executing initiative (reconcile spawned tasks + spawn the next wave). Terminal
|
|
@@ -24,27 +25,26 @@ export function resolveSweepInterval(env = process.env) {
|
|
|
24
25
|
}
|
|
25
26
|
/**
|
|
26
27
|
* Start the periodic initiative-loop sweep. Runs once immediately then on the resolved interval
|
|
27
|
-
* (default one minute; see {@link resolveSweepInterval})
|
|
28
|
-
*
|
|
28
|
+
* (default one minute; see {@link resolveSweepInterval}), non-overlapping + best-effort (see
|
|
29
|
+
* {@link startSweeper}). The non-overlap guard matters most here: `runDue` reconciles spawned
|
|
30
|
+
* tasks and spawns the next wave, so two concurrent passes could both observe "no active run"
|
|
31
|
+
* and double-spawn. Returns a stop function that clears the timer.
|
|
29
32
|
*/
|
|
30
33
|
export function startInitiativeLoopSweeper(container, clock, log, intervalMs = resolveSweepInterval()) {
|
|
31
34
|
const initiatives = container.initiatives;
|
|
32
35
|
if (!initiatives)
|
|
33
36
|
return () => { };
|
|
34
|
-
|
|
35
|
-
|
|
37
|
+
return startSweeper({
|
|
38
|
+
name: 'initiative-loop',
|
|
39
|
+
intervalMs,
|
|
40
|
+
log,
|
|
41
|
+
failureMessage: 'initiative-loop sweep failed',
|
|
42
|
+
tick: async () => {
|
|
36
43
|
const { spawned, completed } = await initiatives.loop.runDue(clock.now());
|
|
37
44
|
if (spawned > 0 || completed > 0) {
|
|
38
45
|
log.info({ spawned, completed }, 'ticked initiative loop');
|
|
39
46
|
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
log.error({ err: error instanceof Error ? error.message : String(error) }, 'initiative-loop sweep failed');
|
|
43
|
-
}
|
|
44
|
-
};
|
|
45
|
-
void tick();
|
|
46
|
-
const timer = setInterval(() => void tick(), intervalMs);
|
|
47
|
-
timer.unref?.();
|
|
48
|
-
return () => clearInterval(timer);
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
49
|
}
|
|
50
50
|
//# sourceMappingURL=initiativeLoop.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"initiativeLoop.js","sourceRoot":"","sources":["../src/initiativeLoop.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"initiativeLoop.js","sourceRoot":"","sources":["../src/initiativeLoop.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAE3C,8FAA8F;AAC9F,+FAA+F;AAC/F,6FAA6F;AAC7F,2FAA2F;AAC3F,kCAAkC;AAElC,4FAA4F;AAC5F,MAAM,iCAAiC,GAAG,EAAE,GAAG,IAAI,CAAA;AAEnD;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,oBAAoB,CAAC,GAAG,GAAsB,OAAO,CAAC,GAAG;IACvE,MAAM,GAAG,GAAG,GAAG,CAAC,2BAA2B,CAAA;IAC3C,MAAM,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAA;IAC7C,OAAO,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,iCAAiC,CAAA;AAC3F,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,0BAA0B,CACxC,SAA0B,EAC1B,KAAY,EACZ,GAAW,EACX,UAAU,GAAW,oBAAoB,EAAE;IAE3C,MAAM,WAAW,GAAG,SAAS,CAAC,WAAW,CAAA;IACzC,IAAI,CAAC,WAAW;QAAE,OAAO,GAAG,EAAE,GAAE,CAAC,CAAA;IACjC,OAAO,YAAY,CAAC;QAClB,IAAI,EAAE,iBAAiB;QACvB,UAAU;QACV,GAAG;QACH,cAAc,EAAE,8BAA8B;QAC9C,IAAI,EAAE,KAAK,IAAI,EAAE;YACf,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,MAAM,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAA;YACzE,IAAI,OAAO,GAAG,CAAC,IAAI,SAAS,GAAG,CAAC,EAAE,CAAC;gBACjC,GAAG,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,wBAAwB,CAAC,CAAA;YAC5D,CAAC;QACH,CAAC;KACF,CAAC,CAAA;AACJ,CAAC"}
|
package/dist/kaizen.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { Clock } from '@cat-factory/kernel';
|
|
2
2
|
import type { Logger, ServerContainer } from '@cat-factory/server';
|
|
3
3
|
/**
|
|
4
|
-
* Start the periodic Kaizen grading sweep. Runs once immediately then on
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Start the periodic Kaizen grading sweep. Runs once immediately then on the interval,
|
|
5
|
+
* non-overlapping + best-effort (see {@link startSweeper}). Returns a stop function that
|
|
6
|
+
* clears the timer.
|
|
7
7
|
*/
|
|
8
8
|
export declare function startKaizenSweeper(container: ServerContainer, clock: Clock, log: Logger): () => void;
|
|
9
9
|
//# sourceMappingURL=kaizen.d.ts.map
|
package/dist/kaizen.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"kaizen.d.ts","sourceRoot":"","sources":["../src/kaizen.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAA;AAChD,OAAO,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"kaizen.d.ts","sourceRoot":"","sources":["../src/kaizen.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAA;AAChD,OAAO,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAelE;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,eAAe,EAC1B,KAAK,EAAE,KAAK,EACZ,GAAG,EAAE,MAAM,GACV,MAAM,IAAI,CAgBZ"}
|
package/dist/kaizen.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { startSweeper } from './sweeper.js';
|
|
1
2
|
// Periodic Kaizen grading sweep for the Node facade — the analogue of the Worker's
|
|
2
3
|
// every-2-min cron call to `kaizen.service.runPending`. The engine only inserts
|
|
3
4
|
// `scheduled` rows at run completion, so this timer does the actual LLM grading (and
|
|
@@ -9,36 +10,24 @@ const KAIZEN_STALE_MS = 10 * 60 * 1000;
|
|
|
9
10
|
/** Max gradings to run per pass (each is an LLM call; keep the batch small). */
|
|
10
11
|
const KAIZEN_SWEEP_BATCH = 5;
|
|
11
12
|
/**
|
|
12
|
-
* Start the periodic Kaizen grading sweep. Runs once immediately then on
|
|
13
|
-
*
|
|
14
|
-
*
|
|
13
|
+
* Start the periodic Kaizen grading sweep. Runs once immediately then on the interval,
|
|
14
|
+
* non-overlapping + best-effort (see {@link startSweeper}). Returns a stop function that
|
|
15
|
+
* clears the timer.
|
|
15
16
|
*/
|
|
16
17
|
export function startKaizenSweeper(container, clock, log) {
|
|
17
18
|
const kaizen = container.kaizen;
|
|
18
19
|
if (!kaizen)
|
|
19
20
|
return () => { };
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
running = true;
|
|
27
|
-
try {
|
|
21
|
+
return startSweeper({
|
|
22
|
+
name: 'kaizen',
|
|
23
|
+
intervalMs: KAIZEN_SWEEP_INTERVAL_MS,
|
|
24
|
+
log,
|
|
25
|
+
failureMessage: 'kaizen sweep failed',
|
|
26
|
+
tick: async () => {
|
|
28
27
|
const processed = await kaizen.service.runPending(clock.now() - KAIZEN_STALE_MS, KAIZEN_SWEEP_BATCH);
|
|
29
28
|
if (processed > 0)
|
|
30
29
|
log.info({ processed }, 'ran pending kaizen gradings');
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
log.error({ err: error instanceof Error ? error.message : String(error) }, 'kaizen sweep failed');
|
|
34
|
-
}
|
|
35
|
-
finally {
|
|
36
|
-
running = false;
|
|
37
|
-
}
|
|
38
|
-
};
|
|
39
|
-
void tick();
|
|
40
|
-
const timer = setInterval(() => void tick(), KAIZEN_SWEEP_INTERVAL_MS);
|
|
41
|
-
timer.unref?.();
|
|
42
|
-
return () => clearInterval(timer);
|
|
30
|
+
},
|
|
31
|
+
});
|
|
43
32
|
}
|
|
44
33
|
//# sourceMappingURL=kaizen.js.map
|
package/dist/kaizen.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"kaizen.js","sourceRoot":"","sources":["../src/kaizen.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"kaizen.js","sourceRoot":"","sources":["../src/kaizen.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAE3C,mFAAmF;AACnF,gFAAgF;AAChF,qFAAqF;AACrF,wFAAwF;AAExF,2FAA2F;AAC3F,MAAM,wBAAwB,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAA;AAC9C,uFAAuF;AACvF,MAAM,eAAe,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAA;AACtC,gFAAgF;AAChF,MAAM,kBAAkB,GAAG,CAAC,CAAA;AAE5B;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAChC,SAA0B,EAC1B,KAAY,EACZ,GAAW;IAEX,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,CAAA;IAC/B,IAAI,CAAC,MAAM;QAAE,OAAO,GAAG,EAAE,GAAE,CAAC,CAAA;IAC5B,OAAO,YAAY,CAAC;QAClB,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE,wBAAwB;QACpC,GAAG;QACH,cAAc,EAAE,qBAAqB;QACrC,IAAI,EAAE,KAAK,IAAI,EAAE;YACf,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,UAAU,CAC/C,KAAK,CAAC,GAAG,EAAE,GAAG,eAAe,EAC7B,kBAAkB,CACnB,CAAA;YACD,IAAI,SAAS,GAAG,CAAC;gBAAE,GAAG,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,EAAE,6BAA6B,CAAC,CAAA;QAC3E,CAAC;KACF,CAAC,CAAA;AACJ,CAAC"}
|
package/dist/notifications.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { Clock } from '@cat-factory/kernel';
|
|
2
2
|
import { type Logger, type ServerContainer } from '@cat-factory/server';
|
|
3
3
|
/**
|
|
4
|
-
* Start the periodic notification-escalation sweep. Runs once immediately then on
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Start the periodic notification-escalation sweep. Runs once immediately then on the
|
|
5
|
+
* interval, non-overlapping + best-effort (see {@link startSweeper}). Returns a stop
|
|
6
|
+
* function that clears the timer.
|
|
7
7
|
*/
|
|
8
8
|
export declare function startNotificationEscalationSweeper(container: ServerContainer, clock: Clock, log: Logger): () => void;
|
|
9
9
|
//# sourceMappingURL=notifications.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"notifications.d.ts","sourceRoot":"","sources":["../src/notifications.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAA;AAChD,OAAO,EAA8B,KAAK,MAAM,EAAE,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"notifications.d.ts","sourceRoot":"","sources":["../src/notifications.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAA;AAChD,OAAO,EAA8B,KAAK,MAAM,EAAE,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAYnG;;;;GAIG;AACH,wBAAgB,kCAAkC,CAChD,SAAS,EAAE,eAAe,EAC1B,KAAK,EAAE,KAAK,EACZ,GAAG,EAAE,MAAM,GACV,MAAM,IAAI,CAYZ"}
|
package/dist/notifications.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { escalateStaleNotifications } from '@cat-factory/server';
|
|
2
|
+
import { startSweeper } from './sweeper.js';
|
|
2
3
|
// Periodic notification-escalation sweep for the Node facade — the analogue of the
|
|
3
4
|
// Worker's every-2-min cron call to `escalateStaleNotifications`. Runs no longer time out
|
|
4
5
|
// waiting for a human, so a notification that has waited past its workspace's
|
|
@@ -7,26 +8,23 @@ import { escalateStaleNotifications } from '@cat-factory/server';
|
|
|
7
8
|
/** How often the Node service escalates long-waiting notifications. */
|
|
8
9
|
const NOTIFICATION_ESCALATION_INTERVAL_MS = 60 * 1000;
|
|
9
10
|
/**
|
|
10
|
-
* Start the periodic notification-escalation sweep. Runs once immediately then on
|
|
11
|
-
*
|
|
12
|
-
*
|
|
11
|
+
* Start the periodic notification-escalation sweep. Runs once immediately then on the
|
|
12
|
+
* interval, non-overlapping + best-effort (see {@link startSweeper}). Returns a stop
|
|
13
|
+
* function that clears the timer.
|
|
13
14
|
*/
|
|
14
15
|
export function startNotificationEscalationSweeper(container, clock, log) {
|
|
15
16
|
if (!container.notifications)
|
|
16
17
|
return () => { };
|
|
17
|
-
|
|
18
|
-
|
|
18
|
+
return startSweeper({
|
|
19
|
+
name: 'notification-escalation',
|
|
20
|
+
intervalMs: NOTIFICATION_ESCALATION_INTERVAL_MS,
|
|
21
|
+
log,
|
|
22
|
+
failureMessage: 'notification escalation failed',
|
|
23
|
+
tick: async () => {
|
|
19
24
|
const escalated = await escalateStaleNotifications(container, clock.now());
|
|
20
25
|
if (escalated > 0)
|
|
21
26
|
log.info({ escalated }, 'escalated notifications');
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
log.error({ err: error instanceof Error ? error.message : String(error) }, 'notification escalation failed');
|
|
25
|
-
}
|
|
26
|
-
};
|
|
27
|
-
void tick();
|
|
28
|
-
const timer = setInterval(() => void tick(), NOTIFICATION_ESCALATION_INTERVAL_MS);
|
|
29
|
-
timer.unref?.();
|
|
30
|
-
return () => clearInterval(timer);
|
|
27
|
+
},
|
|
28
|
+
});
|
|
31
29
|
}
|
|
32
30
|
//# sourceMappingURL=notifications.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"notifications.js","sourceRoot":"","sources":["../src/notifications.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,0BAA0B,EAAqC,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"notifications.js","sourceRoot":"","sources":["../src/notifications.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,0BAA0B,EAAqC,MAAM,qBAAqB,CAAA;AACnG,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAE3C,mFAAmF;AACnF,0FAA0F;AAC1F,8EAA8E;AAC9E,0FAA0F;AAC1F,kFAAkF;AAElF,uEAAuE;AACvE,MAAM,mCAAmC,GAAG,EAAE,GAAG,IAAI,CAAA;AAErD;;;;GAIG;AACH,MAAM,UAAU,kCAAkC,CAChD,SAA0B,EAC1B,KAAY,EACZ,GAAW;IAEX,IAAI,CAAC,SAAS,CAAC,aAAa;QAAE,OAAO,GAAG,EAAE,GAAE,CAAC,CAAA;IAC7C,OAAO,YAAY,CAAC;QAClB,IAAI,EAAE,yBAAyB;QAC/B,UAAU,EAAE,mCAAmC;QAC/C,GAAG;QACH,cAAc,EAAE,gCAAgC;QAChD,IAAI,EAAE,KAAK,IAAI,EAAE;YACf,MAAM,SAAS,GAAG,MAAM,0BAA0B,CAAC,SAAS,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,CAAA;YAC1E,IAAI,SAAS,GAAG,CAAC;gBAAE,GAAG,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,EAAE,yBAAyB,CAAC,CAAA;QACvE,CAAC;KACF,CAAC,CAAA;AACJ,CAAC"}
|
package/dist/recurring.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { Clock } from '@cat-factory/kernel';
|
|
2
2
|
import type { Logger, ServerContainer } from '@cat-factory/server';
|
|
3
3
|
/**
|
|
4
|
-
* Start the periodic schedule sweep. Runs once immediately then on
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Start the periodic schedule sweep. Runs once immediately then on the interval,
|
|
5
|
+
* non-overlapping + best-effort (see {@link startSweeper}). Returns a stop function that
|
|
6
|
+
* clears the timer.
|
|
7
7
|
*/
|
|
8
8
|
export declare function startScheduleSweeper(container: ServerContainer, clock: Clock, log: Logger): () => void;
|
|
9
9
|
//# sourceMappingURL=recurring.d.ts.map
|
package/dist/recurring.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recurring.d.ts","sourceRoot":"","sources":["../src/recurring.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAA;AAChD,OAAO,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"recurring.d.ts","sourceRoot":"","sources":["../src/recurring.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAA;AAChD,OAAO,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAYlE;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,eAAe,EAC1B,KAAK,EAAE,KAAK,EACZ,GAAG,EAAE,MAAM,GACV,MAAM,IAAI,CAeZ"}
|
package/dist/recurring.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { startSweeper } from './sweeper.js';
|
|
1
2
|
// Periodic recurring-pipeline sweep for the Node facade — the analogue of the
|
|
2
3
|
// Worker's every-2-min cron call to `runDue`. The Node service has no cron, so a
|
|
3
4
|
// timer fires every due schedule (the actual cadence is hours; a frequent tick just
|
|
@@ -6,28 +7,25 @@
|
|
|
6
7
|
/** How often the Node service checks for due schedules. */
|
|
7
8
|
const SCHEDULE_SWEEP_INTERVAL_MS = 60 * 1000;
|
|
8
9
|
/**
|
|
9
|
-
* Start the periodic schedule sweep. Runs once immediately then on
|
|
10
|
-
*
|
|
11
|
-
*
|
|
10
|
+
* Start the periodic schedule sweep. Runs once immediately then on the interval,
|
|
11
|
+
* non-overlapping + best-effort (see {@link startSweeper}). Returns a stop function that
|
|
12
|
+
* clears the timer.
|
|
12
13
|
*/
|
|
13
14
|
export function startScheduleSweeper(container, clock, log) {
|
|
14
15
|
const recurring = container.recurring;
|
|
15
16
|
if (!recurring)
|
|
16
17
|
return () => { };
|
|
17
|
-
|
|
18
|
-
|
|
18
|
+
return startSweeper({
|
|
19
|
+
name: 'recurring-pipelines',
|
|
20
|
+
intervalMs: SCHEDULE_SWEEP_INTERVAL_MS,
|
|
21
|
+
log,
|
|
22
|
+
failureMessage: 'recurring-pipeline sweep failed',
|
|
23
|
+
tick: async () => {
|
|
19
24
|
const { fired, skipped } = await recurring.service.runDue(clock.now());
|
|
20
25
|
if (fired > 0 || skipped > 0) {
|
|
21
26
|
log.info({ fired, skipped }, 'fired recurring pipelines');
|
|
22
27
|
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
log.error({ err: error instanceof Error ? error.message : String(error) }, 'recurring-pipeline sweep failed');
|
|
26
|
-
}
|
|
27
|
-
};
|
|
28
|
-
void tick();
|
|
29
|
-
const timer = setInterval(() => void tick(), SCHEDULE_SWEEP_INTERVAL_MS);
|
|
30
|
-
timer.unref?.();
|
|
31
|
-
return () => clearInterval(timer);
|
|
28
|
+
},
|
|
29
|
+
});
|
|
32
30
|
}
|
|
33
31
|
//# sourceMappingURL=recurring.js.map
|
package/dist/recurring.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recurring.js","sourceRoot":"","sources":["../src/recurring.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"recurring.js","sourceRoot":"","sources":["../src/recurring.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAE3C,8EAA8E;AAC9E,iFAAiF;AACjF,oFAAoF;AACpF,mFAAmF;AACnF,eAAe;AAEf,2DAA2D;AAC3D,MAAM,0BAA0B,GAAG,EAAE,GAAG,IAAI,CAAA;AAE5C;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAClC,SAA0B,EAC1B,KAAY,EACZ,GAAW;IAEX,MAAM,SAAS,GAAG,SAAS,CAAC,SAAS,CAAA;IACrC,IAAI,CAAC,SAAS;QAAE,OAAO,GAAG,EAAE,GAAE,CAAC,CAAA;IAC/B,OAAO,YAAY,CAAC;QAClB,IAAI,EAAE,qBAAqB;QAC3B,UAAU,EAAE,0BAA0B;QACtC,GAAG;QACH,cAAc,EAAE,iCAAiC;QACjD,IAAI,EAAE,KAAK,IAAI,EAAE;YACf,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAA;YACtE,IAAI,KAAK,GAAG,CAAC,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;gBAC7B,GAAG,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,2BAA2B,CAAC,CAAA;YAC3D,CAAC;QACH,CAAC;KACF,CAAC,CAAA;AACJ,CAAC"}
|
package/dist/retention.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"retention.d.ts","sourceRoot":"","sources":["../src/retention.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,8BAA8B,EAC9B,0BAA0B,EAC1B,0BAA0B,EAC1B,KAAK,EACL,0BAA0B,EAC1B,uBAAuB,EACvB,sBAAsB,EACtB,4BAA4B,EAC5B,0BAA0B,EAC1B,yBAAyB,EACzB,gCAAgC,EAChC,gCAAgC,EAChC,oBAAoB,EACpB,mBAAmB,EACnB,2BAA2B,EAC5B,MAAM,qBAAqB,CAAA;AAG5B,OAAO,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"retention.d.ts","sourceRoot":"","sources":["../src/retention.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,8BAA8B,EAC9B,0BAA0B,EAC1B,0BAA0B,EAC1B,KAAK,EACL,0BAA0B,EAC1B,uBAAuB,EACvB,sBAAsB,EACtB,4BAA4B,EAC5B,0BAA0B,EAC1B,yBAAyB,EACzB,gCAAgC,EAChC,gCAAgC,EAChC,oBAAoB,EACpB,mBAAmB,EACnB,2BAA2B,EAC5B,MAAM,qBAAqB,CAAA;AAG5B,OAAO,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAwBlE,+DAA+D;AAC/D,MAAM,WAAW,cAAc;IAC7B,oBAAoB,EAAE,IAAI,CAAC,oBAAoB,EAAE,iBAAiB,CAAC,CAAA;IACnE,uBAAuB,EAAE,IAAI,CAAC,uBAAuB,EAAE,iBAAiB,CAAC,CAAA;IAEzE,8BAA8B,EAAE,IAAI,CAAC,8BAA8B,EAAE,iBAAiB,CAAC,CAAA;IAEvF,0BAA0B,EAAE,IAAI,CAAC,0BAA0B,EAAE,iBAAiB,CAAC,CAAA;IAC/E,0BAA0B,EAAE,IAAI,CAAC,0BAA0B,EAAE,iBAAiB,CAAC,CAAA;IAG/E,gCAAgC,EAAE,IAAI,CAAC,gCAAgC,EAAE,eAAe,CAAC,CAAA;IAEzF,gCAAgC,EAAE,IAAI,CAAC,gCAAgC,EAAE,iBAAiB,CAAC,CAAA;IAE3F,yBAAyB,EAAE,IAAI,CAAC,yBAAyB,EAAE,iBAAiB,CAAC,CAAA;IAE7E,4BAA4B,EAAE,IAAI,CAAC,4BAA4B,EAAE,eAAe,CAAC,CAAA;IAKjF,gBAAgB,EAAE,IAAI,CAAC,0BAA0B,EAAE,iBAAiB,CAAC,CAAA;IAGrE,sBAAsB,EAAE,IAAI,CAAC,sBAAsB,EAAE,yBAAyB,CAAC,CAAA;CAChF;AAED,mDAAmD;AACnD,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,CAAA;IAClB,cAAc,EAAE,MAAM,CAAA;IACtB,qBAAqB,EAAE,MAAM,CAAA;IAC7B,kBAAkB,EAAE,MAAM,CAAA;IAC1B,YAAY,EAAE,MAAM,CAAA;IACpB,WAAW,EAAE,MAAM,CAAA;IACnB,uBAAuB,EAAE,MAAM,CAAA;IAC/B,eAAe,EAAE,MAAM,CAAA;IACvB,mBAAmB,EAAE,MAAM,CAAA;IAC3B,OAAO,EAAE,MAAM,CAAA;IACf,aAAa,EAAE,MAAM,CAAA;CACtB;AAmBD;;;;GAIG;AACH,wBAAsB,cAAc,CAClC,KAAK,EAAE,cAAc,EACrB,SAAS,EAAE,eAAe,EAC1B,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,eAAe,CAAC,CAqC1B;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,cAAc,EACrB,SAAS,EAAE,eAAe,EAC1B,KAAK,EAAE,KAAK,EACZ,GAAG,EAAE,MAAM,GACV,MAAM,IAAI,CAaZ;AAED;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CAC3C,YAAY,EAAE,0BAA0B,EACxC,mBAAmB,EAAE,IAAI,CAAC,mBAAmB,EAAE,aAAa,CAAC,EAC7D,kBAAkB,EAAE,IAAI,CAAC,2BAA2B,EAAE,KAAK,CAAC,EAC5D,KAAK,EAAE,KAAK,EACZ,GAAG,EAAE,MAAM,GACV,MAAM,IAAI,CAuBZ"}
|
package/dist/retention.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { DEFAULT_WORKSPACE_SETTINGS } from '@cat-factory/kernel';
|
|
2
2
|
import { sweepBinaryArtifactRetention } from '@cat-factory/orchestration';
|
|
3
|
+
import { startSweeper } from './sweeper.js';
|
|
3
4
|
/** Recurring-pipeline run history is kept ~1 week (the inspector's window). */
|
|
4
5
|
const SCHEDULE_RUN_RETENTION_MS = 7 * 24 * 60 * 60 * 1000;
|
|
5
6
|
/**
|
|
@@ -55,21 +56,18 @@ export async function sweepRetention(repos, retention, now) {
|
|
|
55
56
|
* a stop function that clears the timer.
|
|
56
57
|
*/
|
|
57
58
|
export function startRetentionSweeper(repos, retention, clock, log) {
|
|
58
|
-
|
|
59
|
-
|
|
59
|
+
return startSweeper({
|
|
60
|
+
name: 'retention',
|
|
61
|
+
intervalMs: RETENTION_SWEEP_INTERVAL_MS,
|
|
62
|
+
log,
|
|
63
|
+
failureMessage: 'retention sweep failed',
|
|
64
|
+
tick: async () => {
|
|
60
65
|
const reclaimed = await sweepRetention(repos, retention, clock.now());
|
|
61
66
|
if (Object.values(reclaimed).some((n) => n > 0)) {
|
|
62
67
|
log.info(reclaimed, 'retention sweep reclaimed rows');
|
|
63
68
|
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
log.error({ err: error instanceof Error ? error.message : String(error) }, 'retention sweep failed');
|
|
67
|
-
}
|
|
68
|
-
};
|
|
69
|
-
void tick();
|
|
70
|
-
const timer = setInterval(() => void tick(), RETENTION_SWEEP_INTERVAL_MS);
|
|
71
|
-
timer.unref?.(); // never keep the process alive on the sweep timer alone
|
|
72
|
-
return () => clearInterval(timer);
|
|
69
|
+
},
|
|
70
|
+
});
|
|
73
71
|
}
|
|
74
72
|
/**
|
|
75
73
|
* Start the per-workspace binary-artifact retention sweep (the Node analogue of the Worker's
|
|
@@ -79,8 +77,12 @@ export function startRetentionSweeper(repos, retention, clock, log) {
|
|
|
79
77
|
* once immediately then hourly; best-effort. Returns a stop function.
|
|
80
78
|
*/
|
|
81
79
|
export function startArtifactRetentionSweeper(resolveStore, workspaceRepository, settingsRepository, clock, log) {
|
|
82
|
-
|
|
83
|
-
|
|
80
|
+
return startSweeper({
|
|
81
|
+
name: 'artifact-retention',
|
|
82
|
+
intervalMs: RETENTION_SWEEP_INTERVAL_MS,
|
|
83
|
+
log,
|
|
84
|
+
failureMessage: 'artifact retention sweep failed',
|
|
85
|
+
tick: async () => {
|
|
84
86
|
const removed = await sweepBinaryArtifactRetention({
|
|
85
87
|
resolveStore,
|
|
86
88
|
listWorkspaceIds: () => workspaceRepository.listVisible(null).then((ws) => ws.map((w) => w.id)),
|
|
@@ -91,14 +93,7 @@ export function startArtifactRetentionSweeper(resolveStore, workspaceRepository,
|
|
|
91
93
|
});
|
|
92
94
|
if (removed > 0)
|
|
93
95
|
log.info({ binaryArtifacts: removed }, 'artifact retention sweep reclaimed rows');
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
log.error({ err: error instanceof Error ? error.message : String(error) }, 'artifact retention sweep failed');
|
|
97
|
-
}
|
|
98
|
-
};
|
|
99
|
-
void tick();
|
|
100
|
-
const timer = setInterval(() => void tick(), RETENTION_SWEEP_INTERVAL_MS);
|
|
101
|
-
timer.unref?.();
|
|
102
|
-
return () => clearInterval(timer);
|
|
96
|
+
},
|
|
97
|
+
});
|
|
103
98
|
}
|
|
104
99
|
//# sourceMappingURL=retention.js.map
|
package/dist/retention.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"retention.js","sourceRoot":"","sources":["../src/retention.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAA;AAChE,OAAO,EAAE,4BAA4B,EAAE,MAAM,4BAA4B,CAAA;
|
|
1
|
+
{"version":3,"file":"retention.js","sourceRoot":"","sources":["../src/retention.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { Logger } from '@cat-factory/server';
|
|
2
|
+
/** A best-effort periodic sweep started via {@link startSweeper}. */
|
|
3
|
+
export interface SweeperOptions {
|
|
4
|
+
/** Short sweep name, used as the toad-scheduler task id (so a scheduler-surfaced error names its sweep). */
|
|
5
|
+
name: string;
|
|
6
|
+
/** How often to run the sweep. */
|
|
7
|
+
intervalMs: number;
|
|
8
|
+
/** Logger for the best-effort failure line. */
|
|
9
|
+
log: Logger;
|
|
10
|
+
/** The message logged (with the error) when a pass throws. */
|
|
11
|
+
failureMessage: string;
|
|
12
|
+
/** One sweep pass. Any success logging lives inside it; throws are caught + logged. */
|
|
13
|
+
tick: () => Promise<void>;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Start a periodic, non-overlapping, best-effort sweep. Runs `tick` once immediately then
|
|
17
|
+
* on the interval; skips a tick while the previous pass is still in flight
|
|
18
|
+
* (`preventOverrun`); logs (never throws) a failed pass; never keeps the process alive on
|
|
19
|
+
* the sweep timer alone (`unref`, matching the hand-rolled `setInterval(...).unref()`
|
|
20
|
+
* timers this replaced). Returns a stop function that halts the job — still call it on
|
|
21
|
+
* shutdown so a long pass in flight can't outlive the rest of the teardown.
|
|
22
|
+
*/
|
|
23
|
+
export declare function startSweeper(options: SweeperOptions): () => void;
|
|
24
|
+
//# sourceMappingURL=sweeper.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sweeper.d.ts","sourceRoot":"","sources":["../src/sweeper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAiBjD,qEAAqE;AACrE,MAAM,WAAW,cAAc;IAC7B,4GAA4G;IAC5G,IAAI,EAAE,MAAM,CAAA;IACZ,kCAAkC;IAClC,UAAU,EAAE,MAAM,CAAA;IAClB,+CAA+C;IAC/C,GAAG,EAAE,MAAM,CAAA;IACX,8DAA8D;IAC9D,cAAc,EAAE,MAAM,CAAA;IACtB,uFAAuF;IACvF,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAC1B;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM,IAAI,CAYhE"}
|
package/dist/sweeper.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { AsyncTask, SimpleIntervalJob, ToadScheduler } from 'toad-scheduler';
|
|
2
|
+
/**
|
|
3
|
+
* Start a periodic, non-overlapping, best-effort sweep. Runs `tick` once immediately then
|
|
4
|
+
* on the interval; skips a tick while the previous pass is still in flight
|
|
5
|
+
* (`preventOverrun`); logs (never throws) a failed pass; never keeps the process alive on
|
|
6
|
+
* the sweep timer alone (`unref`, matching the hand-rolled `setInterval(...).unref()`
|
|
7
|
+
* timers this replaced). Returns a stop function that halts the job — still call it on
|
|
8
|
+
* shutdown so a long pass in flight can't outlive the rest of the teardown.
|
|
9
|
+
*/
|
|
10
|
+
export function startSweeper(options) {
|
|
11
|
+
const { name, intervalMs, log, failureMessage, tick } = options;
|
|
12
|
+
const scheduler = new ToadScheduler();
|
|
13
|
+
const task = new AsyncTask(name, tick, (error) => {
|
|
14
|
+
log.error({ err: error instanceof Error ? error.message : String(error) }, failureMessage);
|
|
15
|
+
});
|
|
16
|
+
const job = new SimpleIntervalJob({ milliseconds: intervalMs, runImmediately: true }, task, {
|
|
17
|
+
preventOverrun: true,
|
|
18
|
+
unref: true,
|
|
19
|
+
});
|
|
20
|
+
scheduler.addSimpleIntervalJob(job);
|
|
21
|
+
return () => scheduler.stop();
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=sweeper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sweeper.js","sourceRoot":"","sources":["../src/sweeper.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AA8B5E;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAAC,OAAuB;IAClD,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,cAAc,EAAE,IAAI,EAAE,GAAG,OAAO,CAAA;IAC/D,MAAM,SAAS,GAAG,IAAI,aAAa,EAAE,CAAA;IACrC,MAAM,IAAI,GAAG,IAAI,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,KAAK,EAAE,EAAE;QAC/C,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,cAAc,CAAC,CAAA;IAC5F,CAAC,CAAC,CAAA;IACF,MAAM,GAAG,GAAG,IAAI,iBAAiB,CAAC,EAAE,YAAY,EAAE,UAAU,EAAE,cAAc,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE;QAC1F,cAAc,EAAE,IAAI;QACpB,KAAK,EAAE,IAAI;KACZ,CAAC,CAAA;IACF,SAAS,CAAC,oBAAoB,CAAC,GAAG,CAAC,CAAA;IACnC,OAAO,GAAG,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,CAAA;AAC/B,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cat-factory/node-server",
|
|
3
|
-
"version": "0.92.
|
|
3
|
+
"version": "0.92.9",
|
|
4
4
|
"description": "Node.js runtime facade for the Agent Architecture Board: serves the shared @cat-factory/server Hono app via @hono/node-server, wiring Node implementations of the runtime ports (persistence, gateways, model provisioning).",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -31,24 +31,25 @@
|
|
|
31
31
|
"layered-loader": "^14.5.3",
|
|
32
32
|
"pg": "^8.22.0",
|
|
33
33
|
"pg-boss": "^12.25.1",
|
|
34
|
+
"toad-scheduler": "^4.1.0",
|
|
34
35
|
"ws": "^8.21.0",
|
|
35
|
-
"@cat-factory/agents": "0.
|
|
36
|
-
"@cat-factory/caching": "0.6.
|
|
37
|
-
"@cat-factory/consensus": "0.10.
|
|
38
|
-
"@cat-factory/contracts": "0.
|
|
39
|
-
"@cat-factory/eks": "0.1.
|
|
40
|
-
"@cat-factory/gates": "0.5.
|
|
41
|
-
"@cat-factory/gitlab": "0.7.
|
|
42
|
-
"@cat-factory/integrations": "0.81.
|
|
43
|
-
"@cat-factory/kernel": "0.121.
|
|
44
|
-
"@cat-factory/observability-langfuse": "0.7.
|
|
45
|
-
"@cat-factory/orchestration": "0.
|
|
46
|
-
"@cat-factory/prompt-fragments": "0.13.
|
|
47
|
-
"@cat-factory/provider-bedrock": "0.7.
|
|
48
|
-
"@cat-factory/provider-cloudflare": "0.7.
|
|
49
|
-
"@cat-factory/provider-s3": "0.2.
|
|
50
|
-
"@cat-factory/server": "0.
|
|
51
|
-
"@cat-factory/spend": "0.12.
|
|
36
|
+
"@cat-factory/agents": "0.54.0",
|
|
37
|
+
"@cat-factory/caching": "0.6.35",
|
|
38
|
+
"@cat-factory/consensus": "0.10.36",
|
|
39
|
+
"@cat-factory/contracts": "0.127.0",
|
|
40
|
+
"@cat-factory/eks": "0.1.58",
|
|
41
|
+
"@cat-factory/gates": "0.5.20",
|
|
42
|
+
"@cat-factory/gitlab": "0.7.58",
|
|
43
|
+
"@cat-factory/integrations": "0.81.6",
|
|
44
|
+
"@cat-factory/kernel": "0.121.2",
|
|
45
|
+
"@cat-factory/observability-langfuse": "0.7.190",
|
|
46
|
+
"@cat-factory/orchestration": "0.106.0",
|
|
47
|
+
"@cat-factory/prompt-fragments": "0.13.13",
|
|
48
|
+
"@cat-factory/provider-bedrock": "0.7.206",
|
|
49
|
+
"@cat-factory/provider-cloudflare": "0.7.207",
|
|
50
|
+
"@cat-factory/provider-s3": "0.2.140",
|
|
51
|
+
"@cat-factory/server": "0.112.0",
|
|
52
|
+
"@cat-factory/spend": "0.12.16"
|
|
52
53
|
},
|
|
53
54
|
"devDependencies": {
|
|
54
55
|
"@types/node": "^26.1.0",
|
|
@@ -57,7 +58,7 @@
|
|
|
57
58
|
"drizzle-kit": "1.0.0-rc.4",
|
|
58
59
|
"typescript": "7.0.1-rc",
|
|
59
60
|
"vitest": "^4.1.9",
|
|
60
|
-
"@cat-factory/conformance": "0.10.
|
|
61
|
+
"@cat-factory/conformance": "0.10.99"
|
|
61
62
|
},
|
|
62
63
|
"optionalDependencies": {
|
|
63
64
|
"ioredis": "^5.11.1"
|