tina4-nodejs 3.13.104 → 3.13.105
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 +16 -2
- package/package.json +1 -1
- package/packages/cli/dist/bin.js +157 -38
- package/packages/core/dist/index.js +157 -38
- package/packages/core/src/queue.ts +75 -18
- package/packages/core/src/queueBackends/liteBackend.ts +17 -1
- package/packages/core/src/queueBackends/mongoBackend.ts +80 -14
- package/packages/orm/dist/index.js +157 -38
- package/packages/orm/src/baseModel.ts +18 -5
- package/packages/orm/src/migration.ts +14 -5
- package/types/core/src/queue.d.ts +41 -4
- package/types/core/src/queueBackends/liteBackend.d.ts +7 -1
- package/types/core/src/queueBackends/mongoBackend.d.ts +7 -2
- package/types/orm/src/baseModel.d.ts +10 -5
|
@@ -297,7 +297,16 @@ const MIGRATION_TABLE = "tina4_migration";
|
|
|
297
297
|
* sql_mode, so they are always correct there.
|
|
298
298
|
*/
|
|
299
299
|
function mt(db: DatabaseAdapter): string {
|
|
300
|
-
|
|
300
|
+
const engine = engineOf(db);
|
|
301
|
+
|
|
302
|
+
// Firebird: leave it UNQUOTED so it folds to the upper-case TINA4_MIGRATION
|
|
303
|
+
// that the PHP and Python masters create. A quoted lower-case identifier is a
|
|
304
|
+
// DIFFERENT, case-sensitive table there, so a quoted spelling cannot see a
|
|
305
|
+
// ledger written by another Tina4 language — while tableExists() matches
|
|
306
|
+
// case-insensitively and reports it present, so the INSERT fails alone.
|
|
307
|
+
if (engine === "firebird") return MIGRATION_TABLE;
|
|
308
|
+
|
|
309
|
+
return engine === "mysql" ? `\`${MIGRATION_TABLE}\`` : `"${MIGRATION_TABLE}"`;
|
|
301
310
|
}
|
|
302
311
|
|
|
303
312
|
/**
|
|
@@ -347,9 +356,9 @@ async function ensureMigrationTableOn(db: DatabaseAdapter): Promise<void> {
|
|
|
347
356
|
id INTEGER NOT NULL PRIMARY KEY,
|
|
348
357
|
migration_name VARCHAR(500) NOT NULL UNIQUE,
|
|
349
358
|
description VARCHAR(500),
|
|
350
|
-
batch INTEGER NOT NULL
|
|
359
|
+
batch INTEGER DEFAULT 1 NOT NULL,
|
|
351
360
|
executed_at VARCHAR(50) NOT NULL,
|
|
352
|
-
passed INTEGER NOT NULL
|
|
361
|
+
passed INTEGER DEFAULT 1 NOT NULL
|
|
353
362
|
)`);
|
|
354
363
|
} else {
|
|
355
364
|
// Engine-aware bookkeeping DDL (non-Firebird). Each engine spells an
|
|
@@ -517,11 +526,11 @@ async function recordApplied(
|
|
|
517
526
|
|
|
518
527
|
if (isFirebirdAdapter(db)) {
|
|
519
528
|
// Firebird: generate the id from the sequence.
|
|
520
|
-
const rows = await adapterQuery<{
|
|
529
|
+
const rows = await adapterQuery<{ next_id: number }>(db,
|
|
521
530
|
"SELECT GEN_ID(GEN_TINA4_MIGRATION_ID, 1) AS NEXT_ID FROM RDB$DATABASE",
|
|
522
531
|
);
|
|
523
532
|
insertCols.unshift("id");
|
|
524
|
-
values.unshift(rows[0]?.
|
|
533
|
+
values.unshift(rows[0]?.next_id ?? 1);
|
|
525
534
|
}
|
|
526
535
|
|
|
527
536
|
const placeholders = insertCols.map(() => "?").join(", ");
|
|
@@ -74,7 +74,13 @@ export interface QueueBackendInterface {
|
|
|
74
74
|
close(): void;
|
|
75
75
|
complete?(queue: string, id: string): void;
|
|
76
76
|
fail?(queue: string, id: string, error: string, maxRetries: number, retryBackoff: number): void;
|
|
77
|
-
|
|
77
|
+
/**
|
|
78
|
+
* Explicit manual re-queue: returns true if the id was found and revived,
|
|
79
|
+
* false otherwise (parity with Python's backend.retry_job()). A backend may
|
|
80
|
+
* legacy-return void; callers coerce a void return to true so nothing that
|
|
81
|
+
* used to be reported as success silently flips to failure.
|
|
82
|
+
*/
|
|
83
|
+
retry?(queue: string, id: string, delaySeconds?: number): boolean | void;
|
|
78
84
|
deadLetters?(queue: string, maxRetries?: number): QueueJob[];
|
|
79
85
|
failed?(queue: string, maxRetries?: number): QueueJob[];
|
|
80
86
|
retryFailed?(queue: string, maxRetries?: number): number;
|
|
@@ -137,7 +143,19 @@ export declare class Queue {
|
|
|
137
143
|
*/
|
|
138
144
|
process(handler: (job: QueueJob | QueueJob[]) => Promise<void> | void, options?: ProcessOptions): void;
|
|
139
145
|
/**
|
|
140
|
-
* Count jobs
|
|
146
|
+
* Count jobs by status. Defaults to "pending".
|
|
147
|
+
*
|
|
148
|
+
* ``"pending"`` counts jobs waiting to be popped -- INCLUDES retryable-
|
|
149
|
+
* but-attempted ones, because they live in the pending queue under the
|
|
150
|
+
* auto-retry lifecycle (see failed()).
|
|
151
|
+
* ``"reserved"`` counts jobs a consumer has popped but not yet
|
|
152
|
+
* completed/failed (in-flight against the visibility timeout).
|
|
153
|
+
* ``"completed"`` counts jobs the consumer has finished successfully.
|
|
154
|
+
* ``"failed"``, ``"dead"``, ``"dead_letter"`` are ALIASES that all count
|
|
155
|
+
* the dead-letter store -- jobs whose attempts >= maxRetries and that
|
|
156
|
+
* have given up. Use deadLetters() to list them. Retryable-but-attempted
|
|
157
|
+
* jobs are NOT counted by size("failed"); use failed() to list them or
|
|
158
|
+
* size("pending") to include them in a total.
|
|
141
159
|
*/
|
|
142
160
|
size(status?: string): number;
|
|
143
161
|
/**
|
|
@@ -172,7 +190,11 @@ export declare class Queue {
|
|
|
172
190
|
/**
|
|
173
191
|
* Get jobs that failed at least once but are still being retried
|
|
174
192
|
* (0 < attempts < maxRetries). These live in the pending queue under the
|
|
175
|
-
* auto-retry lifecycle
|
|
193
|
+
* auto-retry lifecycle (fail() re-queues them with an incremented attempts
|
|
194
|
+
* count and a retryBackoff delay) so pop() picks them up again. They are
|
|
195
|
+
* NOT counted by size("failed") -- that alias counts the dead-letter store,
|
|
196
|
+
* matching deadLetters(). To include retryable-failed jobs in a total, use
|
|
197
|
+
* size("pending"). Terminal failures are returned by deadLetters().
|
|
176
198
|
*/
|
|
177
199
|
failed(): QueueJob[];
|
|
178
200
|
/**
|
|
@@ -184,7 +206,22 @@ export declare class Queue {
|
|
|
184
206
|
*/
|
|
185
207
|
retry(jobId?: string, delaySeconds?: number): boolean;
|
|
186
208
|
/**
|
|
187
|
-
* Get
|
|
209
|
+
* Get jobs that exceeded max_retries -- terminal failures.
|
|
210
|
+
*
|
|
211
|
+
* Same set counted by size("failed") / size("dead") / size("dead_letter")
|
|
212
|
+
* (three aliases for the dead-letter store). To LIST retryable-but-
|
|
213
|
+
* attempted jobs (attempts > 0 AND attempts < maxRetries) that are still
|
|
214
|
+
* being auto-retried, use failed() -- those live in the pending queue and
|
|
215
|
+
* are NOT dead letters.
|
|
216
|
+
*
|
|
217
|
+
* Returns Job objects with the failure reason on ``.error`` (not raw dicts)
|
|
218
|
+
* so callers can iterate uniformly with the rest of the queue API and, in
|
|
219
|
+
* particular, call ``.retry()`` on each to manually revive it:
|
|
220
|
+
*
|
|
221
|
+
* for (const job of queue.deadLetters()) {
|
|
222
|
+
* Log.warn(`revived ${job.id}: ${job.error}`);
|
|
223
|
+
* job.retry();
|
|
224
|
+
* }
|
|
188
225
|
*/
|
|
189
226
|
deadLetters(maxRetries?: number): QueueJob[];
|
|
190
227
|
/**
|
|
@@ -122,7 +122,13 @@ export declare class LiteBackend {
|
|
|
122
122
|
* Explicit re-queue requested by the caller (job.retry()).
|
|
123
123
|
*
|
|
124
124
|
* Always re-enqueues regardless of the retry limit — manual override,
|
|
125
|
-
* distinct from the automatic failJob() path.
|
|
125
|
+
* distinct from the automatic failJob() path. Cleans up BOTH the
|
|
126
|
+
* reservation record AND any dead-letter file for this id, so a caller
|
|
127
|
+
* that iterates deadLetters() and calls .retry() on each doesn't leave
|
|
128
|
+
* the failed/ directory carrying duplicates (PY-12-05, 3.13.105).
|
|
129
|
+
* Aligns with retry(queue, jobId) which had always unlinked the
|
|
130
|
+
* dead-letter file -- two spellings of the same intent that previously
|
|
131
|
+
* diverged.
|
|
126
132
|
*/
|
|
127
133
|
retryJob(queue: string, job: QueueJob, delaySeconds?: number): void;
|
|
128
134
|
}
|
|
@@ -87,8 +87,13 @@ export declare class MongoBackend implements QueueBackend {
|
|
|
87
87
|
* retries remain, else dead-letter. Mirrors the file/lite backend.
|
|
88
88
|
*/
|
|
89
89
|
fail(queue: string, id: string, error: string, maxRetries: number, retryBackoff?: number): void;
|
|
90
|
-
/**
|
|
91
|
-
|
|
90
|
+
/**
|
|
91
|
+
* Revive a specific dead-letter job by id. Returns true if the DL was found
|
|
92
|
+
* and revived, false otherwise (parity with LiteBackend.retry(queue, id)
|
|
93
|
+
* and Python's mongo_backend.retry_job()). Pre-3.13.105 this returned void
|
|
94
|
+
* and Queue.retry(id) reported success for every call, even for unknown ids.
|
|
95
|
+
*/
|
|
96
|
+
retry(queue: string, id: string, delaySeconds?: number): boolean;
|
|
92
97
|
/** Jobs that exceeded max retries (the `<queue>.dead_letter` collection topic). */
|
|
93
98
|
deadLetters(queue: string, maxRetries?: number): QueueJob[];
|
|
94
99
|
/** Jobs that failed but are still eligible for retry (status=failed, attempts < max). */
|
|
@@ -339,11 +339,16 @@ export declare class BaseModel {
|
|
|
339
339
|
/**
|
|
340
340
|
* Invalidate every cached query that touches this model's table.
|
|
341
341
|
*
|
|
342
|
-
* Tag-scoped
|
|
343
|
-
* this table is busted too
|
|
344
|
-
* never touches this table is left intact
|
|
345
|
-
*
|
|
346
|
-
*
|
|
342
|
+
* Tag-scoped in the ORM layer (a cached JOIN on another model that reads
|
|
343
|
+
* this table is busted too because it carries this table's tag; a query
|
|
344
|
+
* that never touches this table is left intact), then cascaded to the
|
|
345
|
+
* DB layer on this model's bound connection so an out-of-band write /
|
|
346
|
+
* deliberate refresh / race-with-another-process cannot leave stale rows
|
|
347
|
+
* in db.fetch()'s persistent cache. Called after every ORM write
|
|
348
|
+
* (save/delete/forceDelete/restore) so a read-after-write never serves
|
|
349
|
+
* a stale/deleted row (CACHE-DEC-01). PY-06-22 (3.13.105) added the
|
|
350
|
+
* DB-layer cascade -- previously the two cache layers disagreed under
|
|
351
|
+
* TINA4_AUTO_CACHING=true + TINA4_DB_CACHE=true.
|
|
347
352
|
*/
|
|
348
353
|
static clearCache(): void;
|
|
349
354
|
/**
|