pixivflow 2.10.30 → 2.11.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.md +17 -15
- package/config/fly-two-bots.example.json +4 -0
- package/dist/commands/SchedulerCommand.d.ts.map +1 -1
- package/dist/commands/SchedulerCommand.js +49 -0
- package/dist/commands/SchedulerCommand.js.map +1 -1
- package/dist/commands/scheduler-runtime.d.ts +2 -1
- package/dist/commands/scheduler-runtime.d.ts.map +1 -1
- package/dist/commands/scheduler-runtime.js +71 -5
- package/dist/commands/scheduler-runtime.js.map +1 -1
- package/dist/config/defaults.d.ts +7 -0
- package/dist/config/defaults.d.ts.map +1 -1
- package/dist/config/defaults.js +7 -0
- package/dist/config/defaults.js.map +1 -1
- package/dist/config/types.d.ts +49 -0
- package/dist/config/types.d.ts.map +1 -1
- package/dist/config/validation.d.ts.map +1 -1
- package/dist/config/validation.js +16 -1
- package/dist/config/validation.js.map +1 -1
- package/dist/delivery/DeliveryOutbox.d.ts +7 -0
- package/dist/delivery/DeliveryOutbox.d.ts.map +1 -1
- package/dist/delivery/DeliveryOutbox.js +12 -0
- package/dist/delivery/DeliveryOutbox.js.map +1 -1
- package/dist/delivery/HttpMultipartDelivery.d.ts.map +1 -1
- package/dist/delivery/HttpMultipartDelivery.js +6 -1
- package/dist/delivery/HttpMultipartDelivery.js.map +1 -1
- package/dist/delivery/types.d.ts +4 -0
- package/dist/delivery/types.d.ts.map +1 -1
- package/dist/download/DownloadManager.d.ts +12 -1
- package/dist/download/DownloadManager.d.ts.map +1 -1
- package/dist/download/DownloadManager.js +15 -0
- package/dist/download/DownloadManager.js.map +1 -1
- package/dist/download/IllustrationDownloader.d.ts +2 -2
- package/dist/download/IllustrationDownloader.d.ts.map +1 -1
- package/dist/download/IllustrationDownloader.js +21 -18
- package/dist/download/IllustrationDownloader.js.map +1 -1
- package/dist/download/UgoiraConverter.d.ts +2 -0
- package/dist/download/UgoiraConverter.d.ts.map +1 -0
- package/dist/download/UgoiraConverter.js +21 -0
- package/dist/download/UgoiraConverter.js.map +1 -0
- package/dist/download/handlers/IllustrationTargetHandler.d.ts.map +1 -1
- package/dist/download/handlers/IllustrationTargetHandler.js +12 -4
- package/dist/download/handlers/IllustrationTargetHandler.js.map +1 -1
- package/dist/download/handlers/NovelTargetHandler.d.ts.map +1 -1
- package/dist/download/handlers/NovelTargetHandler.js +12 -3
- package/dist/download/handlers/NovelTargetHandler.js.map +1 -1
- package/dist/download/pipeline/DownloadPipeline.d.ts +5 -0
- package/dist/download/pipeline/DownloadPipeline.d.ts.map +1 -1
- package/dist/download/pipeline/DownloadPipeline.js +10 -0
- package/dist/download/pipeline/DownloadPipeline.js.map +1 -1
- package/dist/download/ugoira_to_gif.py +65 -0
- package/dist/package.json +1 -1
- package/dist/scheduler/MultiScheduleManager.d.ts +20 -1
- package/dist/scheduler/MultiScheduleManager.d.ts.map +1 -1
- package/dist/scheduler/MultiScheduleManager.js +37 -3
- package/dist/scheduler/MultiScheduleManager.js.map +1 -1
- package/dist/scheduler/ScheduleTriggerServer.d.ts +55 -0
- package/dist/scheduler/ScheduleTriggerServer.d.ts.map +1 -0
- package/dist/scheduler/ScheduleTriggerServer.js +101 -0
- package/dist/scheduler/ScheduleTriggerServer.js.map +1 -0
- package/dist/scheduler/Scheduler.d.ts +12 -3
- package/dist/scheduler/Scheduler.d.ts.map +1 -1
- package/dist/scheduler/Scheduler.js +28 -10
- package/dist/scheduler/Scheduler.js.map +1 -1
- package/dist/scheduler/SlotCoordinator.d.ts +59 -0
- package/dist/scheduler/SlotCoordinator.d.ts.map +1 -0
- package/dist/scheduler/SlotCoordinator.js +150 -0
- package/dist/scheduler/SlotCoordinator.js.map +1 -0
- package/dist/storage/Database.d.ts +4 -0
- package/dist/storage/Database.d.ts.map +1 -1
- package/dist/storage/Database.js +7 -0
- package/dist/storage/Database.js.map +1 -1
- package/dist/storage/DatabaseMigration.d.ts.map +1 -1
- package/dist/storage/DatabaseMigration.js +35 -0
- package/dist/storage/DatabaseMigration.js.map +1 -1
- package/dist/storage/repositories/SlotRepository.d.ts +78 -0
- package/dist/storage/repositories/SlotRepository.d.ts.map +1 -0
- package/dist/storage/repositories/SlotRepository.js +170 -0
- package/dist/storage/repositories/SlotRepository.js.map +1 -0
- package/dist/webui/package.json +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SlotCoordinator = void 0;
|
|
4
|
+
exports.slotNameForNow = slotNameForNow;
|
|
5
|
+
exports.slotDateForNow = slotDateForNow;
|
|
6
|
+
const logger_1 = require("../logger");
|
|
7
|
+
/** Morning cron fires before noon; evening from noon onward (config tz). */
|
|
8
|
+
function slotNameForNow(timezone) {
|
|
9
|
+
const hour = new Date(new Date().toLocaleString('en-US', { timeZone: timezone || 'Asia/Shanghai' })).getHours();
|
|
10
|
+
return hour < 13 ? 'morning' : 'evening';
|
|
11
|
+
}
|
|
12
|
+
/** Today's date (YYYY-MM-DD) in the configured scheduler timezone. */
|
|
13
|
+
function slotDateForNow(timezone) {
|
|
14
|
+
const parts = new Intl.DateTimeFormat('en-CA', {
|
|
15
|
+
timeZone: timezone || 'Asia/Shanghai',
|
|
16
|
+
year: 'numeric',
|
|
17
|
+
month: '2-digit',
|
|
18
|
+
day: '2-digit',
|
|
19
|
+
}).formatToParts(new Date());
|
|
20
|
+
const get = (t) => parts.find((p) => p.type === t)?.value ?? '';
|
|
21
|
+
return `${get('year')}-${get('month')}-${get('day')}`;
|
|
22
|
+
}
|
|
23
|
+
function todayInTz(timezone) {
|
|
24
|
+
return slotDateForNow(timezone);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Owns the Schedule Slot ledger for one scheduler run. Ensures duplicate
|
|
28
|
+
* triggers / restarts converge on one slot, completed cells are not re-run, and
|
|
29
|
+
* a selected work id stays locked across automatic retries.
|
|
30
|
+
*/
|
|
31
|
+
class SlotCoordinator {
|
|
32
|
+
database;
|
|
33
|
+
constructor(database) {
|
|
34
|
+
this.database = database;
|
|
35
|
+
}
|
|
36
|
+
/** Resolve + validate a requested slot against now (never trusts client date). */
|
|
37
|
+
resolveSlot(requested, config) {
|
|
38
|
+
const tz = this.primaryTimezone(config);
|
|
39
|
+
const name = requested === 'evening' ? 'evening' : requested === 'morning' ? 'morning' : slotNameForNow(tz);
|
|
40
|
+
const date = todayInTz(tz);
|
|
41
|
+
const graceMin = config.schedulerRuntime?.trigger?.graceMinutes ?? 90;
|
|
42
|
+
const now = Date.now();
|
|
43
|
+
// Grace window: a slot is runnable if its scheduled time was within the last
|
|
44
|
+
// `graceMin` minutes (resume after a crash) or is still upcoming today.
|
|
45
|
+
const scheduledHour = name === 'morning' ? 10 : 18;
|
|
46
|
+
const sched = new Date(`${date}T${String(scheduledHour).padStart(2, '0')}:00:00`);
|
|
47
|
+
// Compare in tz-agnostic wall clock is imprecise; use a coarse grace check:
|
|
48
|
+
// allow when within [scheduled - small lead, scheduled + grace]. Lead 15m.
|
|
49
|
+
const leadMs = 15 * 60_000;
|
|
50
|
+
const graceMs = graceMin * 60_000;
|
|
51
|
+
if (now < sched.getTime() - leadMs) {
|
|
52
|
+
return { error: `slot ${name} for ${date} is not due yet`, status: 425 };
|
|
53
|
+
}
|
|
54
|
+
if (now > sched.getTime() + graceMs) {
|
|
55
|
+
return { error: `slot ${name} for ${date} has expired (grace ${graceMin}m)`, status: 410 };
|
|
56
|
+
}
|
|
57
|
+
return { slotId: `${date}:${name}`, slotName: name, slotDate: date, triggerSource: 'external' };
|
|
58
|
+
}
|
|
59
|
+
primaryTimezone(config) {
|
|
60
|
+
return config.schedules?.[0]?.timezone ?? config.scheduler?.timezone;
|
|
61
|
+
}
|
|
62
|
+
/** The targets that still need to run for this slot (skips terminal cells). */
|
|
63
|
+
pendingTargets(slotId, targets) {
|
|
64
|
+
const out = [];
|
|
65
|
+
for (const target of targets) {
|
|
66
|
+
if (!target.id)
|
|
67
|
+
continue;
|
|
68
|
+
const cell = this.database.slots.ensureCell(slotId, target.id, target.type);
|
|
69
|
+
if (cell.status === 'submitted' || cell.status === 'no_candidate')
|
|
70
|
+
continue;
|
|
71
|
+
out.push({ target, cell });
|
|
72
|
+
}
|
|
73
|
+
return out;
|
|
74
|
+
}
|
|
75
|
+
/** Open (or resume) a slot and return whether the whole slot is already done. */
|
|
76
|
+
begin(slot, schedule) {
|
|
77
|
+
const { slot: slotRec, created } = this.database.slots.getOrCreateSlot(slot.slotId, {
|
|
78
|
+
slotDate: slot.slotDate,
|
|
79
|
+
slotName: slot.slotName,
|
|
80
|
+
scheduleId: schedule.id,
|
|
81
|
+
triggerSource: slot.triggerSource,
|
|
82
|
+
});
|
|
83
|
+
if (created)
|
|
84
|
+
logger_1.logger.info('Slot started', { slot: slot.slotId, schedule: schedule.id });
|
|
85
|
+
else
|
|
86
|
+
logger_1.logger.info('Slot resumed (duplicate trigger or restart)', { slot: slot.slotId, status: slotRec.status });
|
|
87
|
+
if (slotRec.status === 'success' || slotRec.status === 'partial') {
|
|
88
|
+
return { slotRec, alreadyCompleted: true };
|
|
89
|
+
}
|
|
90
|
+
this.database.slots.markSlotStatus(slot.slotId, 'running');
|
|
91
|
+
return { slotRec, alreadyCompleted: false };
|
|
92
|
+
}
|
|
93
|
+
/** Lock the selected work for a cell (first selection wins; retries keep it). */
|
|
94
|
+
lockWork(slotId, targetId, workId, workType) {
|
|
95
|
+
this.database.slots.ensureCell(slotId, targetId, workType);
|
|
96
|
+
this.database.slots.lockCellWork(slotId, targetId, workId, workType);
|
|
97
|
+
}
|
|
98
|
+
/** Record a cell's terminal state from the download/delivery outcome. */
|
|
99
|
+
markCell(slotId, targetId, status, error) {
|
|
100
|
+
const cell = this.database.slots.getCell(slotId, targetId);
|
|
101
|
+
if (!cell)
|
|
102
|
+
return;
|
|
103
|
+
if (cell.status === 'submitted' && status !== 'submitted')
|
|
104
|
+
return; // never downgrade a delivered cell
|
|
105
|
+
this.database.slots.setCellStatus(slotId, targetId, status, error);
|
|
106
|
+
}
|
|
107
|
+
/** Roll cell results up into the slot status and log a readable summary. */
|
|
108
|
+
finish(slot, schedule, targets) {
|
|
109
|
+
for (const t of targets) {
|
|
110
|
+
if (!t.id)
|
|
111
|
+
continue;
|
|
112
|
+
const cell = this.database.slots.getCell(slot.slotId, t.id);
|
|
113
|
+
if (!cell || cell.status === 'pending' || cell.status === 'selected') {
|
|
114
|
+
// Ran but never reached a terminal state (target threw before delivery).
|
|
115
|
+
if (cell)
|
|
116
|
+
this.database.slots.setCellStatus(slot.slotId, t.id, 'failed', cell.lastError ?? 'target did not complete');
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
const status = this.database.slots.deriveSlotStatus(slot.slotId);
|
|
120
|
+
this.database.slots.markSlotStatus(slot.slotId, status);
|
|
121
|
+
const cells = this.database.slots.getCells(slot.slotId).map((c) => ({
|
|
122
|
+
targetId: c.targetId,
|
|
123
|
+
status: c.status,
|
|
124
|
+
workId: c.workId,
|
|
125
|
+
error: c.lastError,
|
|
126
|
+
}));
|
|
127
|
+
const icon = (s) => s === 'submitted' ? '✅' : s === 'no_candidate' ? '⚠️ no_candidate' : '❌ failed';
|
|
128
|
+
logger_1.logger.info(`Slot ${slot.slotId} ${status}\n` +
|
|
129
|
+
cells.map((c) => ` ${c.targetId.padEnd(28)} ${icon(c.status)} ${c.workId ? '#' + c.workId : ''} ${c.error ? '(' + c.error + ')' : ''}`).join('\n'), { slot: slot.slotId, status });
|
|
130
|
+
return { scheduleId: schedule.id, slotId: slot.slotId, status, alreadyCompleted: false, cells };
|
|
131
|
+
}
|
|
132
|
+
completedSummary(slotId, schedule) {
|
|
133
|
+
const cells = this.database.slots.getCells(slotId).map((c) => ({
|
|
134
|
+
targetId: c.targetId,
|
|
135
|
+
status: c.status,
|
|
136
|
+
workId: c.workId,
|
|
137
|
+
error: c.lastError,
|
|
138
|
+
}));
|
|
139
|
+
const slotRec = this.database.slots.getSlot(slotId);
|
|
140
|
+
return {
|
|
141
|
+
scheduleId: schedule.id,
|
|
142
|
+
slotId,
|
|
143
|
+
status: slotRec?.status ?? 'success',
|
|
144
|
+
alreadyCompleted: true,
|
|
145
|
+
cells,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
exports.SlotCoordinator = SlotCoordinator;
|
|
150
|
+
//# sourceMappingURL=SlotCoordinator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SlotCoordinator.js","sourceRoot":"","sources":["../../src/scheduler/SlotCoordinator.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { IDatabase } from '../interfaces/IDatabase';
|
|
2
|
+
import { SlotRepository } from './repositories/SlotRepository';
|
|
2
3
|
export interface AccessTokenStore {
|
|
3
4
|
accessToken: string;
|
|
4
5
|
expiresAt: number;
|
|
@@ -36,10 +37,13 @@ export declare class Database implements IDatabase {
|
|
|
36
37
|
private schedulerRepo;
|
|
37
38
|
private configHistoryRepo;
|
|
38
39
|
private taskHistoryRepo;
|
|
40
|
+
private slotRepo;
|
|
39
41
|
constructor(databasePath: string);
|
|
40
42
|
migrate(): void;
|
|
41
43
|
/** Absolute path of the SQLite file (used to locate sibling cache dirs). */
|
|
42
44
|
getDatabasePath(): string;
|
|
45
|
+
/** Schedule Slot ledger (business-level idempotency for scheduled batches). */
|
|
46
|
+
get slots(): SlotRepository;
|
|
43
47
|
getToken(key: string): AccessTokenStore | null;
|
|
44
48
|
setToken(key: string, value: AccessTokenStore): void;
|
|
45
49
|
deleteToken(key: string): boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Database.d.ts","sourceRoot":"","sources":["../../src/storage/Database.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"Database.d.ts","sourceRoot":"","sources":["../../src/storage/Database.ts"],"names":[],"mappings":"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"}
|
package/dist/storage/Database.js
CHANGED
|
@@ -16,6 +16,7 @@ const ExecutionRepository_1 = require("./repositories/ExecutionRepository");
|
|
|
16
16
|
const SchedulerRepository_1 = require("./repositories/SchedulerRepository");
|
|
17
17
|
const ConfigHistoryRepository_1 = require("./repositories/ConfigHistoryRepository");
|
|
18
18
|
const TaskHistoryRepository_1 = require("./repositories/TaskHistoryRepository");
|
|
19
|
+
const SlotRepository_1 = require("./repositories/SlotRepository");
|
|
19
20
|
class Database {
|
|
20
21
|
databasePath;
|
|
21
22
|
db;
|
|
@@ -26,6 +27,7 @@ class Database {
|
|
|
26
27
|
schedulerRepo;
|
|
27
28
|
configHistoryRepo;
|
|
28
29
|
taskHistoryRepo;
|
|
30
|
+
slotRepo;
|
|
29
31
|
constructor(databasePath) {
|
|
30
32
|
this.databasePath = databasePath;
|
|
31
33
|
try {
|
|
@@ -48,6 +50,7 @@ class Database {
|
|
|
48
50
|
this.schedulerRepo = new SchedulerRepository_1.SchedulerRepository(this.db);
|
|
49
51
|
this.configHistoryRepo = new ConfigHistoryRepository_1.ConfigHistoryRepository(this.db);
|
|
50
52
|
this.taskHistoryRepo = new TaskHistoryRepository_1.TaskHistoryRepository(this.db);
|
|
53
|
+
this.slotRepo = new SlotRepository_1.SlotRepository(this.db);
|
|
51
54
|
}
|
|
52
55
|
catch (error) {
|
|
53
56
|
throw new errors_1.DatabaseError(`Failed to initialize database at ${this.databasePath}`, error instanceof Error ? error : undefined);
|
|
@@ -63,6 +66,10 @@ class Database {
|
|
|
63
66
|
// delivery-outbox) always land beside the real database regardless of CWD.
|
|
64
67
|
return (0, node_path_1.isAbsolute)(this.databasePath) ? this.databasePath : (0, node_path_1.resolve)(process.cwd(), this.databasePath);
|
|
65
68
|
}
|
|
69
|
+
/** Schedule Slot ledger (business-level idempotency for scheduled batches). */
|
|
70
|
+
get slots() {
|
|
71
|
+
return this.slotRepo;
|
|
72
|
+
}
|
|
66
73
|
// Token management - delegated to TokenRepository
|
|
67
74
|
getToken(key) {
|
|
68
75
|
return this.tokenRepo.getToken(key);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Database.js","sourceRoot":"","sources":["../../src/storage/Database.ts"],"names":[],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"Database.js","sourceRoot":"","sources":["../../src/storage/Database.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DatabaseMigration.d.ts","sourceRoot":"","sources":["../../src/storage/DatabaseMigration.ts"],"names":[],"mappings":"AAAA,OAAO,cAAc,MAAM,gBAAgB,CAAC;AAI5C;;GAEG;AACH,qBAAa,iBAAiB;IAChB,OAAO,CAAC,QAAQ,CAAC,EAAE;gBAAF,EAAE,EAAE,cAAc,CAAC,QAAQ;IAExD;;OAEG;IACI,OAAO,IAAI,IAAI;
|
|
1
|
+
{"version":3,"file":"DatabaseMigration.d.ts","sourceRoot":"","sources":["../../src/storage/DatabaseMigration.ts"],"names":[],"mappings":"AAAA,OAAO,cAAc,MAAM,gBAAgB,CAAC;AAI5C;;GAEG;AACH,qBAAa,iBAAiB;IAChB,OAAO,CAAC,QAAQ,CAAC,EAAE;gBAAF,EAAE,EAAE,cAAc,CAAC,QAAQ;IAExD;;OAEG;IACI,OAAO,IAAI,IAAI;CAyKvB"}
|
|
@@ -74,6 +74,38 @@ class DatabaseMigration {
|
|
|
74
74
|
progress_message TEXT,
|
|
75
75
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
76
76
|
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
77
|
+
)`,
|
|
78
|
+
// Schedule Slots: one business batch (e.g. 2026-09-08:morning). A slot
|
|
79
|
+
// groups one run of each enabled target (a "cell"). External triggers
|
|
80
|
+
// and restarts converge on the SAME slot row instead of re-running.
|
|
81
|
+
`CREATE TABLE IF NOT EXISTS schedule_slots (
|
|
82
|
+
id TEXT PRIMARY KEY,
|
|
83
|
+
slot_date TEXT NOT NULL,
|
|
84
|
+
slot_name TEXT NOT NULL,
|
|
85
|
+
schedule_id TEXT NOT NULL,
|
|
86
|
+
status TEXT NOT NULL DEFAULT 'pending',
|
|
87
|
+
trigger_source TEXT,
|
|
88
|
+
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
89
|
+
started_at DATETIME,
|
|
90
|
+
completed_at DATETIME,
|
|
91
|
+
last_error TEXT
|
|
92
|
+
)`,
|
|
93
|
+
// One cell per (slot, target). UNIQUE(slot_id, target_id) is the core
|
|
94
|
+
// business idempotency: a given slot can never emit two works for one
|
|
95
|
+
// target even under duplicate triggers / restarts / outbox replay.
|
|
96
|
+
`CREATE TABLE IF NOT EXISTS schedule_slot_items (
|
|
97
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
98
|
+
slot_id TEXT NOT NULL,
|
|
99
|
+
target_id TEXT NOT NULL,
|
|
100
|
+
work_id TEXT,
|
|
101
|
+
work_type TEXT,
|
|
102
|
+
status TEXT NOT NULL DEFAULT 'pending',
|
|
103
|
+
attempt_count INTEGER NOT NULL DEFAULT 0,
|
|
104
|
+
last_error TEXT,
|
|
105
|
+
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
106
|
+
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
107
|
+
completed_at DATETIME,
|
|
108
|
+
UNIQUE(slot_id, target_id)
|
|
77
109
|
)`,
|
|
78
110
|
];
|
|
79
111
|
// Create indexes for better query performance
|
|
@@ -88,6 +120,9 @@ class DatabaseMigration {
|
|
|
88
120
|
`CREATE INDEX IF NOT EXISTS idx_task_history_task_id ON task_history(task_id)`,
|
|
89
121
|
`CREATE INDEX IF NOT EXISTS idx_task_history_status ON task_history(status)`,
|
|
90
122
|
`CREATE INDEX IF NOT EXISTS idx_task_history_start_time ON task_history(start_time)`,
|
|
123
|
+
`CREATE INDEX IF NOT EXISTS idx_slots_date ON schedule_slots(slot_date, slot_name)`,
|
|
124
|
+
`CREATE INDEX IF NOT EXISTS idx_slot_items_slot ON schedule_slot_items(slot_id)`,
|
|
125
|
+
`CREATE INDEX IF NOT EXISTS idx_slot_items_work ON schedule_slot_items(work_id, work_type)`,
|
|
91
126
|
];
|
|
92
127
|
const transaction = this.db.transaction((stmts) => {
|
|
93
128
|
for (const sql of stmts) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DatabaseMigration.js","sourceRoot":"","sources":["../../src/storage/DatabaseMigration.ts"],"names":[],"mappings":";;;AACA,4CAAgD;AAChD,sCAAmC;AAEnC;;GAEG;AACH,MAAa,iBAAiB;IACC;IAA7B,YAA6B,EAA2B;QAA3B,OAAE,GAAF,EAAE,CAAyB;IAAG,CAAC;IAE5D;;OAEG;IACI,OAAO;QACZ,IAAI,CAAC;YACH,MAAM,UAAU,GAAG;gBACjB;;;;YAII;gBACJ;;;;;;;;;;;YAWI;gBACJ;;;;;;;YAOI;gBACJ;;;;;;;;;;YAUI;gBACJ;;;;;;;YAOI;gBACJ;;;;;;;;;;;;;YAaI;aACL,CAAC;YAEF,8CAA8C;YAC9C,MAAM,OAAO,GAAG;gBACd,qFAAqF;gBACrF,gEAAgE;gBAChE,oFAAoF;gBACpF,mFAAmF;gBACnF,sGAAsG;gBACtG,4FAA4F;gBAC5F,wFAAwF;gBACxF,8EAA8E;gBAC9E,4EAA4E;gBAC5E,oFAAoF;
|
|
1
|
+
{"version":3,"file":"DatabaseMigration.js","sourceRoot":"","sources":["../../src/storage/DatabaseMigration.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { BaseRepository } from './BaseRepository';
|
|
2
|
+
export type SlotStatus = 'pending' | 'running' | 'success' | 'partial' | 'failed' | 'expired';
|
|
3
|
+
export type CellStatus = 'pending' | 'selected' | 'submitted' | 'no_candidate' | 'failed';
|
|
4
|
+
export interface SlotRecord {
|
|
5
|
+
id: string;
|
|
6
|
+
slotDate: string;
|
|
7
|
+
slotName: string;
|
|
8
|
+
scheduleId: string;
|
|
9
|
+
status: SlotStatus;
|
|
10
|
+
triggerSource: string | null;
|
|
11
|
+
createdAt: string;
|
|
12
|
+
startedAt: string | null;
|
|
13
|
+
completedAt: string | null;
|
|
14
|
+
lastError: string | null;
|
|
15
|
+
}
|
|
16
|
+
export interface SlotItemRecord {
|
|
17
|
+
id: number;
|
|
18
|
+
slotId: string;
|
|
19
|
+
targetId: string;
|
|
20
|
+
workId: string | null;
|
|
21
|
+
workType: string | null;
|
|
22
|
+
status: CellStatus;
|
|
23
|
+
attemptCount: number;
|
|
24
|
+
lastError: string | null;
|
|
25
|
+
createdAt: string;
|
|
26
|
+
updatedAt: string;
|
|
27
|
+
completedAt: string | null;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Durable ledger for Schedule Slots and their per-target cells.
|
|
31
|
+
*
|
|
32
|
+
* A slot is one business batch (e.g. `2026-09-08:morning`). Each enabled target
|
|
33
|
+
* owns exactly one cell in a slot, enforced by UNIQUE(slot_id, target_id). This
|
|
34
|
+
* is the business-level idempotency layer above TelePost's work-level
|
|
35
|
+
* idempotency: duplicate triggers / restarts / outbox replays all converge on
|
|
36
|
+
* the same row instead of emitting a second work for the same slot/target.
|
|
37
|
+
*/
|
|
38
|
+
export declare class SlotRepository extends BaseRepository {
|
|
39
|
+
/**
|
|
40
|
+
* Fetch an existing slot or create it. Returns the row plus `created:false`
|
|
41
|
+
* when a slot with this id already existed (the caller should resume it, not
|
|
42
|
+
* start a fresh run).
|
|
43
|
+
*/
|
|
44
|
+
getOrCreateSlot(id: string, data: {
|
|
45
|
+
slotDate: string;
|
|
46
|
+
slotName: string;
|
|
47
|
+
scheduleId: string;
|
|
48
|
+
triggerSource?: string;
|
|
49
|
+
}): {
|
|
50
|
+
slot: SlotRecord;
|
|
51
|
+
created: boolean;
|
|
52
|
+
};
|
|
53
|
+
getSlot(id: string): SlotRecord | null;
|
|
54
|
+
getSlotsForDate(slotDate: string): SlotRecord[];
|
|
55
|
+
getRecentSlots(limit?: number): SlotRecord[];
|
|
56
|
+
markSlotStatus(id: string, status: SlotStatus, error?: string): void;
|
|
57
|
+
/** All cells for a slot (one per target). */
|
|
58
|
+
getCells(slotId: string): SlotItemRecord[];
|
|
59
|
+
getCell(slotId: string, targetId: string): SlotItemRecord | null;
|
|
60
|
+
/** Create the cell row if it does not exist (idempotent). */
|
|
61
|
+
ensureCell(slotId: string, targetId: string, workType: string): SlotItemRecord;
|
|
62
|
+
/**
|
|
63
|
+
* Lock the selected work for a cell. The first selection wins; later calls
|
|
64
|
+
* (automatic retries, outbox replay, duplicate triggers) never overwrite it —
|
|
65
|
+
* candidate replacement is a separate explicit operator action (clearCellWork).
|
|
66
|
+
*/
|
|
67
|
+
lockCellWork(slotId: string, targetId: string, workId: string, workType: string): SlotItemRecord;
|
|
68
|
+
/** Explicit operator action: forget the locked work so a re-run picks another candidate. */
|
|
69
|
+
clearCellWork(slotId: string, targetId: string): void;
|
|
70
|
+
setCellStatus(slotId: string, targetId: string, status: CellStatus, error?: string): void;
|
|
71
|
+
/** Work ids already locked in THIS slot (to stop two cells taking the same work). */
|
|
72
|
+
getLockedWorkIds(slotId: string): Set<string>;
|
|
73
|
+
/** Roll up a slot's status from its cells. */
|
|
74
|
+
deriveSlotStatus(slotId: string): SlotStatus;
|
|
75
|
+
private toSlot;
|
|
76
|
+
private toItem;
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=SlotRepository.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SlotRepository.d.ts","sourceRoot":"","sources":["../../../src/storage/repositories/SlotRepository.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SlotRepository = void 0;
|
|
4
|
+
const BaseRepository_1 = require("./BaseRepository");
|
|
5
|
+
/**
|
|
6
|
+
* Durable ledger for Schedule Slots and their per-target cells.
|
|
7
|
+
*
|
|
8
|
+
* A slot is one business batch (e.g. `2026-09-08:morning`). Each enabled target
|
|
9
|
+
* owns exactly one cell in a slot, enforced by UNIQUE(slot_id, target_id). This
|
|
10
|
+
* is the business-level idempotency layer above TelePost's work-level
|
|
11
|
+
* idempotency: duplicate triggers / restarts / outbox replays all converge on
|
|
12
|
+
* the same row instead of emitting a second work for the same slot/target.
|
|
13
|
+
*/
|
|
14
|
+
class SlotRepository extends BaseRepository_1.BaseRepository {
|
|
15
|
+
/**
|
|
16
|
+
* Fetch an existing slot or create it. Returns the row plus `created:false`
|
|
17
|
+
* when a slot with this id already existed (the caller should resume it, not
|
|
18
|
+
* start a fresh run).
|
|
19
|
+
*/
|
|
20
|
+
getOrCreateSlot(id, data) {
|
|
21
|
+
const insert = this.db.prepare(`INSERT INTO schedule_slots (id, slot_date, slot_name, schedule_id, status, trigger_source)
|
|
22
|
+
VALUES (@id, @slotDate, @slotName, @scheduleId, 'pending', @triggerSource)
|
|
23
|
+
ON CONFLICT(id) DO NOTHING`);
|
|
24
|
+
const info = insert.run({
|
|
25
|
+
id,
|
|
26
|
+
slotDate: data.slotDate,
|
|
27
|
+
slotName: data.slotName,
|
|
28
|
+
scheduleId: data.scheduleId,
|
|
29
|
+
triggerSource: data.triggerSource ?? null,
|
|
30
|
+
});
|
|
31
|
+
const created = info.changes > 0;
|
|
32
|
+
return { slot: this.getSlot(id), created };
|
|
33
|
+
}
|
|
34
|
+
getSlot(id) {
|
|
35
|
+
const row = this.db.prepare(`SELECT * FROM schedule_slots WHERE id = ?`).get(id);
|
|
36
|
+
return row ? this.toSlot(row) : null;
|
|
37
|
+
}
|
|
38
|
+
getSlotsForDate(slotDate) {
|
|
39
|
+
const rows = this.db
|
|
40
|
+
.prepare(`SELECT * FROM schedule_slots WHERE slot_date = ? ORDER BY id ASC`)
|
|
41
|
+
.all(slotDate);
|
|
42
|
+
return rows.map((r) => this.toSlot(r));
|
|
43
|
+
}
|
|
44
|
+
getRecentSlots(limit = 14) {
|
|
45
|
+
const rows = this.db
|
|
46
|
+
.prepare(`SELECT * FROM schedule_slots ORDER BY id DESC LIMIT ?`)
|
|
47
|
+
.all(limit);
|
|
48
|
+
return rows.map((r) => this.toSlot(r));
|
|
49
|
+
}
|
|
50
|
+
markSlotStatus(id, status, error) {
|
|
51
|
+
const stamp = status === 'running' ? 'started_at' : status === 'success' || status === 'partial' || status === 'failed' ? 'completed_at' : null;
|
|
52
|
+
const sets = ['status = @status', 'last_error = @error'];
|
|
53
|
+
if (stamp === 'started_at')
|
|
54
|
+
sets.push('started_at = CURRENT_TIMESTAMP');
|
|
55
|
+
if (stamp === 'completed_at')
|
|
56
|
+
sets.push('completed_at = CURRENT_TIMESTAMP');
|
|
57
|
+
this.db
|
|
58
|
+
.prepare(`UPDATE schedule_slots SET ${sets.join(', ')} WHERE id = @id`)
|
|
59
|
+
.run({ id, status, error: error ?? null });
|
|
60
|
+
}
|
|
61
|
+
/** All cells for a slot (one per target). */
|
|
62
|
+
getCells(slotId) {
|
|
63
|
+
const rows = this.db
|
|
64
|
+
.prepare(`SELECT * FROM schedule_slot_items WHERE slot_id = ? ORDER BY target_id ASC`)
|
|
65
|
+
.all(slotId);
|
|
66
|
+
return rows.map((r) => this.toItem(r));
|
|
67
|
+
}
|
|
68
|
+
getCell(slotId, targetId) {
|
|
69
|
+
const row = this.db
|
|
70
|
+
.prepare(`SELECT * FROM schedule_slot_items WHERE slot_id = ? AND target_id = ?`)
|
|
71
|
+
.get(slotId, targetId);
|
|
72
|
+
return row ? this.toItem(row) : null;
|
|
73
|
+
}
|
|
74
|
+
/** Create the cell row if it does not exist (idempotent). */
|
|
75
|
+
ensureCell(slotId, targetId, workType) {
|
|
76
|
+
this.db
|
|
77
|
+
.prepare(`INSERT INTO schedule_slot_items (slot_id, target_id, work_type, status)
|
|
78
|
+
VALUES (@slotId, @targetId, @workType, 'pending')
|
|
79
|
+
ON CONFLICT(slot_id, target_id) DO NOTHING`)
|
|
80
|
+
.run({ slotId, targetId, workType });
|
|
81
|
+
return this.getCell(slotId, targetId);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Lock the selected work for a cell. The first selection wins; later calls
|
|
85
|
+
* (automatic retries, outbox replay, duplicate triggers) never overwrite it —
|
|
86
|
+
* candidate replacement is a separate explicit operator action (clearCellWork).
|
|
87
|
+
*/
|
|
88
|
+
lockCellWork(slotId, targetId, workId, workType) {
|
|
89
|
+
this.db
|
|
90
|
+
.prepare(`UPDATE schedule_slot_items
|
|
91
|
+
SET work_id = COALESCE(work_id, @workId),
|
|
92
|
+
work_type = CASE WHEN work_id IS NULL THEN @workType ELSE work_type END,
|
|
93
|
+
status = CASE WHEN status = 'pending' THEN 'selected' ELSE status END,
|
|
94
|
+
attempt_count = attempt_count + 1,
|
|
95
|
+
updated_at = CURRENT_TIMESTAMP
|
|
96
|
+
WHERE slot_id = @slotId AND target_id = @targetId`)
|
|
97
|
+
.run({ slotId, targetId, workId, workType });
|
|
98
|
+
return this.getCell(slotId, targetId);
|
|
99
|
+
}
|
|
100
|
+
/** Explicit operator action: forget the locked work so a re-run picks another candidate. */
|
|
101
|
+
clearCellWork(slotId, targetId) {
|
|
102
|
+
this.db
|
|
103
|
+
.prepare(`UPDATE schedule_slot_items
|
|
104
|
+
SET work_id = NULL, status = 'pending', last_error = NULL,
|
|
105
|
+
completed_at = NULL, updated_at = CURRENT_TIMESTAMP
|
|
106
|
+
WHERE slot_id = @slotId AND target_id = @targetId`)
|
|
107
|
+
.run({ slotId, targetId });
|
|
108
|
+
}
|
|
109
|
+
setCellStatus(slotId, targetId, status, error) {
|
|
110
|
+
const terminal = status === 'submitted' || status === 'no_candidate' || status === 'failed';
|
|
111
|
+
const sets = ['status = @status', 'last_error = @error', 'updated_at = CURRENT_TIMESTAMP'];
|
|
112
|
+
if (terminal)
|
|
113
|
+
sets.push('completed_at = CURRENT_TIMESTAMP');
|
|
114
|
+
this.db
|
|
115
|
+
.prepare(`UPDATE schedule_slot_items SET ${sets.join(', ')} WHERE slot_id = @slotId AND target_id = @targetId`)
|
|
116
|
+
.run({ slotId, targetId, status, error: error ?? null });
|
|
117
|
+
}
|
|
118
|
+
/** Work ids already locked in THIS slot (to stop two cells taking the same work). */
|
|
119
|
+
getLockedWorkIds(slotId) {
|
|
120
|
+
const rows = this.db
|
|
121
|
+
.prepare(`SELECT work_id FROM schedule_slot_items WHERE slot_id = ? AND work_id IS NOT NULL`)
|
|
122
|
+
.all(slotId);
|
|
123
|
+
return new Set(rows.map((r) => r.work_id));
|
|
124
|
+
}
|
|
125
|
+
/** Roll up a slot's status from its cells. */
|
|
126
|
+
deriveSlotStatus(slotId) {
|
|
127
|
+
const cells = this.getCells(slotId);
|
|
128
|
+
if (cells.length === 0)
|
|
129
|
+
return 'pending';
|
|
130
|
+
const terminal = cells.filter((c) => c.status === 'submitted' || c.status === 'no_candidate' || c.status === 'failed');
|
|
131
|
+
if (terminal.length < cells.length)
|
|
132
|
+
return 'running';
|
|
133
|
+
if (cells.every((c) => c.status === 'submitted'))
|
|
134
|
+
return 'success';
|
|
135
|
+
if (cells.some((c) => c.status === 'submitted'))
|
|
136
|
+
return 'partial';
|
|
137
|
+
return 'failed';
|
|
138
|
+
}
|
|
139
|
+
toSlot(row) {
|
|
140
|
+
return {
|
|
141
|
+
id: row.id,
|
|
142
|
+
slotDate: row.slot_date,
|
|
143
|
+
slotName: row.slot_name,
|
|
144
|
+
scheduleId: row.schedule_id,
|
|
145
|
+
status: row.status,
|
|
146
|
+
triggerSource: row.trigger_source,
|
|
147
|
+
createdAt: row.created_at,
|
|
148
|
+
startedAt: row.started_at,
|
|
149
|
+
completedAt: row.completed_at,
|
|
150
|
+
lastError: row.last_error,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
toItem(row) {
|
|
154
|
+
return {
|
|
155
|
+
id: row.id,
|
|
156
|
+
slotId: row.slot_id,
|
|
157
|
+
targetId: row.target_id,
|
|
158
|
+
workId: row.work_id,
|
|
159
|
+
workType: row.work_type,
|
|
160
|
+
status: row.status,
|
|
161
|
+
attemptCount: row.attempt_count,
|
|
162
|
+
lastError: row.last_error,
|
|
163
|
+
createdAt: row.created_at,
|
|
164
|
+
updatedAt: row.updated_at,
|
|
165
|
+
completedAt: row.completed_at,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
exports.SlotRepository = SlotRepository;
|
|
170
|
+
//# sourceMappingURL=SlotRepository.js.map
|