pixivflow 2.20.5 → 2.22.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/README.en.md +179 -56
- package/README.md +110 -57
- package/dist/commands/SchedulerCommand.js +63 -0
- package/dist/commands/SchedulerIdleLifecycle.d.ts +8 -0
- package/dist/commands/SchedulerIdleLifecycle.js +2 -1
- package/dist/commands/scheduler-runtime.js +17 -0
- package/dist/config/types.d.ts +26 -0
- package/dist/config/validation.js +21 -0
- package/dist/delivery/types.d.ts +15 -0
- package/dist/notification/NotificationPolicy.d.ts +2 -0
- package/dist/notification/NotificationPolicy.js +18 -1
- package/dist/package.json +1 -1
- package/dist/scheduler/MultiScheduleManager.d.ts +12 -1
- package/dist/scheduler/MultiScheduleManager.js +46 -50
- package/dist/scheduler/RecoveryPolicy.d.ts +45 -0
- package/dist/scheduler/RecoveryPolicy.js +63 -0
- package/dist/scheduler/ResourceAdmission.d.ts +68 -0
- package/dist/scheduler/ResourceAdmission.js +83 -0
- package/dist/scheduler/ScheduleTriggerServer.d.ts +16 -0
- package/dist/scheduler/ScheduleTriggerServer.js +55 -0
- package/dist/scheduler/Scheduler.d.ts +19 -2
- package/dist/scheduler/Scheduler.js +12 -3
- package/dist/scheduler/SlotCoordinator.d.ts +20 -0
- package/dist/scheduler/SlotCoordinator.js +44 -2
- package/dist/scheduler/TargetOutcome.d.ts +31 -0
- package/dist/scheduler/TargetOutcome.js +128 -0
- package/dist/storage/DatabaseMigration.js +17 -0
- package/dist/storage/repositories/SlotRepository.d.ts +29 -0
- package/dist/storage/repositories/SlotRepository.js +28 -2
- package/dist/version.js +1 -1
- package/dist/webui/package.json +1 -1
- package/package.json +2 -2
|
@@ -29,6 +29,15 @@ export interface SlotRecord {
|
|
|
29
29
|
manualRequestId: string | null;
|
|
30
30
|
/** Opaque caller correlation (review chain / review id); null unless manual. */
|
|
31
31
|
correlationId: string | null;
|
|
32
|
+
/**
|
|
33
|
+
* Request UUID of a remote MANUAL RECOVERY run (§manual-recovery); null for
|
|
34
|
+
* scheduled occurrences and review refetches. A recovery slot re-runs the
|
|
35
|
+
* failed target(s) under a per-occurrence recovery policy and reports its
|
|
36
|
+
* outcome through the schedule-outcome channel.
|
|
37
|
+
*/
|
|
38
|
+
recoveryRequestId: string | null;
|
|
39
|
+
/** Recovery policy preset ('normal'|'relaxed'); null for non-recovery slots. */
|
|
40
|
+
recoveryMode: string | null;
|
|
32
41
|
}
|
|
33
42
|
export interface SlotItemRecord {
|
|
34
43
|
id: number;
|
|
@@ -45,6 +54,14 @@ export interface SlotItemRecord {
|
|
|
45
54
|
*/
|
|
46
55
|
fallback_stage: number;
|
|
47
56
|
lastError: string | null;
|
|
57
|
+
/**
|
|
58
|
+
* Normalized terminal failure reason code (§terminal-reason) — one of the
|
|
59
|
+
* stable codes in TargetOutcome's failure taxonomy. Null for non-terminal
|
|
60
|
+
* cells or successful submissions.
|
|
61
|
+
*/
|
|
62
|
+
terminalReasonCode: string | null;
|
|
63
|
+
/** User-facing business message for the terminal reason. */
|
|
64
|
+
terminalReasonMessage: string | null;
|
|
48
65
|
createdAt: string;
|
|
49
66
|
updatedAt: string;
|
|
50
67
|
completedAt: string | null;
|
|
@@ -61,6 +78,8 @@ export interface SlotItemRecord {
|
|
|
61
78
|
export declare class SlotRepository extends BaseRepository {
|
|
62
79
|
/** Exact manual request/target lookup for authenticated convergence checks. */
|
|
63
80
|
findManualSlot(requestId: string, targetId: string): SlotRecord | null;
|
|
81
|
+
/** Exact manual RECOVERY request/target lookup (§manual-recovery). */
|
|
82
|
+
findRecoverySlot(requestId: string, targetId: string): SlotRecord | null;
|
|
64
83
|
/**
|
|
65
84
|
* Fetch an existing slot or create it. On creation the schedule's target
|
|
66
85
|
* membership is snapshotted (target_ids); a later config reload never mutates
|
|
@@ -81,6 +100,10 @@ export declare class SlotRepository extends BaseRepository {
|
|
|
81
100
|
manualRequestId?: string | null;
|
|
82
101
|
/** Opaque caller correlation recorded with a manual slot. */
|
|
83
102
|
correlationId?: string | null;
|
|
103
|
+
/** Manual recovery request UUID (opens a `recover-` slot). */
|
|
104
|
+
recoveryRequestId?: string | null;
|
|
105
|
+
/** Manual recovery policy preset ('normal' | 'relaxed'). */
|
|
106
|
+
recoveryMode?: string | null;
|
|
84
107
|
}): {
|
|
85
108
|
slot: SlotRecord;
|
|
86
109
|
created: boolean;
|
|
@@ -143,6 +166,12 @@ export declare class SlotRepository extends BaseRepository {
|
|
|
143
166
|
bumpFallbackStage(slotId: string, targetId: string, reason: string): number;
|
|
144
167
|
cellFallbackStage(slotId: string, targetId: string): number;
|
|
145
168
|
setCellStatus(slotId: string, targetId: string, status: CellStatus, error?: string): void;
|
|
169
|
+
/**
|
|
170
|
+
* Persist the normalized terminal failure reason for a cell (§terminal-reason).
|
|
171
|
+
* Idempotent; a retried recovery/rollup only ever overwrites with the same or
|
|
172
|
+
* a later reasoned verdict.
|
|
173
|
+
*/
|
|
174
|
+
setCellTerminalReason(slotId: string, targetId: string, code: string, message: string): void;
|
|
146
175
|
/**
|
|
147
176
|
* Transition a cell with FSM validation. Never downgrades a confirmed cell;
|
|
148
177
|
* an illegal transition throws rather than silently corrupting state.
|
|
@@ -17,6 +17,11 @@ class SlotRepository extends BaseRepository_1.BaseRepository {
|
|
|
17
17
|
const rows = this.db.prepare(`SELECT * FROM schedule_slots WHERE manual_request_id = ?`).all(requestId);
|
|
18
18
|
return rows.map((row) => this.toSlot(row)).find((slot) => slot.targetIds.includes(targetId)) ?? null;
|
|
19
19
|
}
|
|
20
|
+
/** Exact manual RECOVERY request/target lookup (§manual-recovery). */
|
|
21
|
+
findRecoverySlot(requestId, targetId) {
|
|
22
|
+
const rows = this.db.prepare(`SELECT * FROM schedule_slots WHERE recovery_request_id = ?`).all(requestId);
|
|
23
|
+
return rows.map((row) => this.toSlot(row)).find((slot) => slot.targetIds.includes(targetId)) ?? null;
|
|
24
|
+
}
|
|
20
25
|
/**
|
|
21
26
|
* Fetch an existing slot or create it. On creation the schedule's target
|
|
22
27
|
* membership is snapshotted (target_ids); a later config reload never mutates
|
|
@@ -26,10 +31,12 @@ class SlotRepository extends BaseRepository_1.BaseRepository {
|
|
|
26
31
|
getOrCreateSlot(id, data) {
|
|
27
32
|
const insert = this.db.prepare(`INSERT INTO schedule_slots
|
|
28
33
|
(id, schedule_id, occurrence_at, occurrence_date, occurrence_label, timezone, target_ids,
|
|
29
|
-
status, trigger_source, slot_date, slot_name, manual_request_id, correlation_id
|
|
34
|
+
status, trigger_source, slot_date, slot_name, manual_request_id, correlation_id,
|
|
35
|
+
recovery_request_id, recovery_mode)
|
|
30
36
|
VALUES
|
|
31
37
|
(@id, @scheduleId, @occurrenceAt, @occurrenceDate, @occurrenceLabel, @timezone, @targetIds,
|
|
32
|
-
'pending', @triggerSource, @slotDate, @slotName, @manualRequestId, @correlationId
|
|
38
|
+
'pending', @triggerSource, @slotDate, @slotName, @manualRequestId, @correlationId,
|
|
39
|
+
@recoveryRequestId, @recoveryMode)
|
|
33
40
|
ON CONFLICT(id) DO NOTHING`);
|
|
34
41
|
const info = insert.run({
|
|
35
42
|
id,
|
|
@@ -44,6 +51,8 @@ class SlotRepository extends BaseRepository_1.BaseRepository {
|
|
|
44
51
|
slotName: data.slotName ?? '',
|
|
45
52
|
manualRequestId: data.manualRequestId ?? null,
|
|
46
53
|
correlationId: data.correlationId ?? null,
|
|
54
|
+
recoveryRequestId: data.recoveryRequestId ?? null,
|
|
55
|
+
recoveryMode: data.recoveryMode ?? null,
|
|
47
56
|
});
|
|
48
57
|
const created = info.changes > 0;
|
|
49
58
|
return { slot: this.getSlot(id), created };
|
|
@@ -244,6 +253,19 @@ class SlotRepository extends BaseRepository_1.BaseRepository {
|
|
|
244
253
|
.prepare(`UPDATE schedule_slot_items SET ${sets.join(', ')} WHERE slot_id = @slotId AND target_id = @targetId`)
|
|
245
254
|
.run({ slotId, targetId, status, error: error ?? null });
|
|
246
255
|
}
|
|
256
|
+
/**
|
|
257
|
+
* Persist the normalized terminal failure reason for a cell (§terminal-reason).
|
|
258
|
+
* Idempotent; a retried recovery/rollup only ever overwrites with the same or
|
|
259
|
+
* a later reasoned verdict.
|
|
260
|
+
*/
|
|
261
|
+
setCellTerminalReason(slotId, targetId, code, message) {
|
|
262
|
+
this.db
|
|
263
|
+
.prepare(`UPDATE schedule_slot_items
|
|
264
|
+
SET terminal_reason_code = @code, terminal_reason_message = @message,
|
|
265
|
+
updated_at = CURRENT_TIMESTAMP
|
|
266
|
+
WHERE slot_id = @slotId AND target_id = @targetId`)
|
|
267
|
+
.run({ slotId, targetId, code: code.slice(0, 64), message: message.slice(0, 400) });
|
|
268
|
+
}
|
|
247
269
|
/**
|
|
248
270
|
* Transition a cell with FSM validation. Never downgrades a confirmed cell;
|
|
249
271
|
* an illegal transition throws rather than silently corrupting state.
|
|
@@ -402,6 +424,8 @@ class SlotRepository extends BaseRepository_1.BaseRepository {
|
|
|
402
424
|
heartbeatAt: row.heartbeat_at ?? null,
|
|
403
425
|
manualRequestId: row.manual_request_id ?? null,
|
|
404
426
|
correlationId: row.correlation_id ?? null,
|
|
427
|
+
recoveryRequestId: row.recovery_request_id ?? null,
|
|
428
|
+
recoveryMode: row.recovery_mode ?? null,
|
|
405
429
|
};
|
|
406
430
|
}
|
|
407
431
|
toItem(row) {
|
|
@@ -415,6 +439,8 @@ class SlotRepository extends BaseRepository_1.BaseRepository {
|
|
|
415
439
|
attemptCount: row.attempt_count,
|
|
416
440
|
fallback_stage: Number(row.fallback_stage ?? 0),
|
|
417
441
|
lastError: row.last_error,
|
|
442
|
+
terminalReasonCode: row.terminal_reason_code ?? null,
|
|
443
|
+
terminalReasonMessage: row.terminal_reason_message ?? null,
|
|
418
444
|
createdAt: row.created_at,
|
|
419
445
|
updatedAt: row.updated_at,
|
|
420
446
|
completedAt: row.completed_at,
|
package/dist/version.js
CHANGED
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.BUILD = void 0;
|
|
4
4
|
// GENERATED by scripts/write-version.js — do not edit manually.
|
|
5
|
-
exports.BUILD = { version: '2.
|
|
5
|
+
exports.BUILD = { version: '2.22.0', commit: 'e6cd6211dba7' };
|
|
6
6
|
//# sourceMappingURL=version.js.map
|
package/dist/webui/package.json
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pixivflow",
|
|
3
|
-
"version": "2.
|
|
4
|
-
"description": "🎨
|
|
3
|
+
"version": "2.22.0",
|
|
4
|
+
"description": "🎨 Pixiv 下载、筛选与自动收集工具 - 批量下载插画和小说、按标签/热度/日期筛选、定时任务与可靠 HTTP 交付 | Pixiv downloader and automation toolkit with filtering, scheduling and reliable HTTP delivery",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "git+https://github.com/redtidev1918/PixivFlow.git"
|