@tribe-nest/forge 1.18.0 → 1.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/server/jobs.ts +31 -6
package/package.json
CHANGED
package/src/server/jobs.ts
CHANGED
|
@@ -24,9 +24,20 @@ interface AppJobsStub {
|
|
|
24
24
|
* and what happened on the LAST delivery attempt. Because jobs fail silently (no
|
|
25
25
|
* logs / dead-letter), this is how you SEE why one didn't run:
|
|
26
26
|
* - `lastDispatchAt` null while `alarmAt` is in the past → the alarm isn't firing;
|
|
27
|
-
* - `lastError` starting "
|
|
27
|
+
* - `lastError` starting "runner unreachable:" → a platform-side fault, not yours;
|
|
28
|
+
* - `lastDispatchStatus` "404" + "no dispatch target" → the platform has no
|
|
29
|
+
* record of where to send your runs; republish the app;
|
|
30
|
+
* - `lastDispatchStatus` "502" → your Worker isn't deployed;
|
|
28
31
|
* - `lastDispatchStatus` "401" → your app was reached but rejected the token
|
|
29
|
-
* (the dispatch-worker's APP_SYNC_SECRET ≠ the backend JWT_SECRET)
|
|
32
|
+
* (the dispatch-worker's APP_SYNC_SECRET ≠ the backend JWT_SECRET);
|
|
33
|
+
* - `lastDispatchStatus` "404" + "unknown job" → the run landed but no handler
|
|
34
|
+
* in your job map has that name.
|
|
35
|
+
*
|
|
36
|
+
* For "my one-time job never ran", read `deadLetters` first. `queueDepth` on its
|
|
37
|
+
* own tells you almost nothing: `enqueueAppJob(..., delayMs: 0)` causes the run
|
|
38
|
+
* to be dispatched and the row deleted within seconds, so depth reads 0 whether
|
|
39
|
+
* the job succeeded or was never enqueued at all. A job that keeps failing
|
|
40
|
+
* retries for ~15 minutes and then appears in `deadLetters` with its error.
|
|
30
41
|
*/
|
|
31
42
|
export interface AppJobsStatus {
|
|
32
43
|
appId: string | null;
|
|
@@ -34,7 +45,13 @@ export interface AppJobsStatus {
|
|
|
34
45
|
alarmAt: number | null;
|
|
35
46
|
schedules: Array<{ name: string; intervalMs: number | null; cron: string | null; nextRun: number }>;
|
|
36
47
|
queueDepth: number;
|
|
48
|
+
/** Names currently queued with their next attempt time. */
|
|
49
|
+
queued: Array<{ name: string; runAt: number; attempts: number }>;
|
|
50
|
+
/** One-time jobs that exhausted their retries and were given up on, newest first. */
|
|
51
|
+
deadLetters: Array<{ name: string; attempts: number; failedAt: number; error: string | null }>;
|
|
37
52
|
lastDispatchAt: number | null;
|
|
53
|
+
/** Which job the last delivery attempt was for — all jobs share one error slot. */
|
|
54
|
+
lastDispatchJob: string | null;
|
|
38
55
|
lastDispatchScript: string | null;
|
|
39
56
|
lastDispatchStatus: string | null;
|
|
40
57
|
lastError: string | null;
|
|
@@ -68,10 +85,18 @@ export type JobHandler = (payload: unknown, env: unknown, ctx: JobContext) => Pr
|
|
|
68
85
|
export interface AppJobsConfig {
|
|
69
86
|
/** The app id (VITE_APP_ID). */
|
|
70
87
|
appId: string;
|
|
71
|
-
/** This Worker's script name in the dispatch namespace (VITE_APP_SCRIPT). */
|
|
72
|
-
script: string;
|
|
73
88
|
/** The TribeNest public API base (VITE_API_URL) — used to verify the callback token. */
|
|
74
89
|
apiUrl: string;
|
|
90
|
+
/**
|
|
91
|
+
* @deprecated No longer needed — leave it unset in new apps.
|
|
92
|
+
*
|
|
93
|
+
* This Worker's script name in the dispatch namespace (VITE_APP_SCRIPT). Your
|
|
94
|
+
* app's address is a PLATFORM fact: it is recorded at publish and resolved by
|
|
95
|
+
* the job runtime from your `appId`, so an app no longer reports where it
|
|
96
|
+
* lives. Still accepted (and forwarded as a fallback hint) so apps published
|
|
97
|
+
* before that change keep dispatching without a rebuild.
|
|
98
|
+
*/
|
|
99
|
+
script?: string;
|
|
75
100
|
}
|
|
76
101
|
|
|
77
102
|
const stub = (env: AppJobsEnv, appId: string): AppJobsStub => env.JOBS.get(env.JOBS.idFromName(appId));
|
|
@@ -93,7 +118,7 @@ function scheduleHash(schedules: JobSchedule[]): string {
|
|
|
93
118
|
* one, a removed one is pruned.
|
|
94
119
|
*/
|
|
95
120
|
export async function reconcileAppJobs(env: AppJobsEnv, cfg: AppJobsConfig, schedules: JobSchedule[]): Promise<void> {
|
|
96
|
-
await stub(env, cfg.appId).reconcile(cfg.script, cfg.appId, schedules, scheduleHash(schedules));
|
|
121
|
+
await stub(env, cfg.appId).reconcile(cfg.script ?? "", cfg.appId, schedules, scheduleHash(schedules));
|
|
97
122
|
}
|
|
98
123
|
|
|
99
124
|
/** Enqueue a durable one-time job (survives redeploys, retried on failure). */
|
|
@@ -104,7 +129,7 @@ export async function enqueueAppJob(
|
|
|
104
129
|
payload?: unknown,
|
|
105
130
|
delayMs = 0,
|
|
106
131
|
): Promise<void> {
|
|
107
|
-
await stub(env, cfg.appId).enqueue(cfg.script, cfg.appId, name, payload ?? null, delayMs);
|
|
132
|
+
await stub(env, cfg.appId).enqueue(cfg.script ?? "", cfg.appId, name, payload ?? null, delayMs);
|
|
108
133
|
}
|
|
109
134
|
|
|
110
135
|
/**
|