pixivflow 2.11.0 → 2.12.1

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.
Files changed (51) hide show
  1. package/README.md +3 -0
  2. package/dist/commands/SchedulerCommand.d.ts.map +1 -1
  3. package/dist/commands/SchedulerCommand.js +79 -32
  4. package/dist/commands/SchedulerCommand.js.map +1 -1
  5. package/dist/commands/SchedulerRunOnceCommand.d.ts.map +1 -1
  6. package/dist/commands/SchedulerRunOnceCommand.js +5 -1
  7. package/dist/commands/SchedulerRunOnceCommand.js.map +1 -1
  8. package/dist/commands/scheduler-runtime.d.ts +4 -2
  9. package/dist/commands/scheduler-runtime.d.ts.map +1 -1
  10. package/dist/commands/scheduler-runtime.js +86 -53
  11. package/dist/commands/scheduler-runtime.js.map +1 -1
  12. package/dist/config/types.d.ts +24 -1
  13. package/dist/config/types.d.ts.map +1 -1
  14. package/dist/delivery/DeliveryOutbox.d.ts.map +1 -1
  15. package/dist/delivery/DeliveryOutbox.js +10 -3
  16. package/dist/delivery/DeliveryOutbox.js.map +1 -1
  17. package/dist/delivery/HttpMultipartDelivery.d.ts.map +1 -1
  18. package/dist/delivery/HttpMultipartDelivery.js +19 -3
  19. package/dist/delivery/HttpMultipartDelivery.js.map +1 -1
  20. package/dist/delivery/types.d.ts +12 -0
  21. package/dist/delivery/types.d.ts.map +1 -1
  22. package/dist/package.json +1 -1
  23. package/dist/scheduler/MultiScheduleManager.d.ts +9 -12
  24. package/dist/scheduler/MultiScheduleManager.d.ts.map +1 -1
  25. package/dist/scheduler/MultiScheduleManager.js +31 -15
  26. package/dist/scheduler/MultiScheduleManager.js.map +1 -1
  27. package/dist/scheduler/OccurrenceResolver.d.ts +90 -0
  28. package/dist/scheduler/OccurrenceResolver.d.ts.map +1 -0
  29. package/dist/scheduler/OccurrenceResolver.js +127 -0
  30. package/dist/scheduler/OccurrenceResolver.js.map +1 -0
  31. package/dist/scheduler/ScheduleTriggerServer.d.ts +35 -30
  32. package/dist/scheduler/ScheduleTriggerServer.d.ts.map +1 -1
  33. package/dist/scheduler/ScheduleTriggerServer.js +25 -27
  34. package/dist/scheduler/ScheduleTriggerServer.js.map +1 -1
  35. package/dist/scheduler/Scheduler.d.ts +5 -3
  36. package/dist/scheduler/Scheduler.d.ts.map +1 -1
  37. package/dist/scheduler/Scheduler.js +9 -6
  38. package/dist/scheduler/Scheduler.js.map +1 -1
  39. package/dist/scheduler/SlotCoordinator.d.ts +51 -20
  40. package/dist/scheduler/SlotCoordinator.d.ts.map +1 -1
  41. package/dist/scheduler/SlotCoordinator.js +98 -72
  42. package/dist/scheduler/SlotCoordinator.js.map +1 -1
  43. package/dist/storage/DatabaseMigration.d.ts.map +1 -1
  44. package/dist/storage/DatabaseMigration.js +42 -5
  45. package/dist/storage/DatabaseMigration.js.map +1 -1
  46. package/dist/storage/repositories/SlotRepository.d.ts +32 -8
  47. package/dist/storage/repositories/SlotRepository.d.ts.map +1 -1
  48. package/dist/storage/repositories/SlotRepository.js +69 -15
  49. package/dist/storage/repositories/SlotRepository.js.map +1 -1
  50. package/dist/webui/package.json +1 -1
  51. package/package.json +1 -1
@@ -1,95 +1,116 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SlotCoordinator = void 0;
4
- exports.slotNameForNow = slotNameForNow;
5
- exports.slotDateForNow = slotDateForNow;
4
+ exports.timezoneForSchedule = timezoneForSchedule;
6
5
  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
- }
6
+ const OccurrenceResolver_1 = require("./OccurrenceResolver");
26
7
  /**
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.
8
+ * Owns the Schedule Slot ledger for one scheduler run. A Slot is one durable
9
+ * execution occurrence of a Schedule (NOT a morning/evening row). It ensures
10
+ * duplicate/concurrent/retry triggers converge on one slot, completed cells are
11
+ * not re-run, target membership is stable once materialized, and a selected
12
+ * work id stays locked across automatic retries.
13
+ *
14
+ * This class is delivery-agnostic: it knows nothing about TelePost, bots, or any
15
+ * hosting platform — only schedules, targets and the slot ledger.
30
16
  */
31
17
  class SlotCoordinator {
32
18
  database;
33
19
  constructor(database) {
34
20
  this.database = database;
35
21
  }
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);
22
+ /**
23
+ * Resolve + validate the canonical occurrence for a trigger. Uses ONLY the
24
+ * schedule's cron + timezone and the trigger instant (never a client-supplied
25
+ * past date). `requestedSlotName` is an optional human label for provenance;
26
+ * identity always derives from the resolved canonical fire time.
27
+ */
28
+ resolveOccurrence(schedule, config, triggerSource, at = new Date(), requestedSlotName) {
41
29
  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 };
30
+ let occurrence;
31
+ try {
32
+ occurrence = (0, OccurrenceResolver_1.resolveOccurrence)({ schedule, at, triggerSource });
53
33
  }
54
- if (now > sched.getTime() + graceMs) {
55
- return { error: `slot ${name} for ${date} has expired (grace ${graceMin}m)`, status: 410 };
34
+ catch (error) {
35
+ return { error: error instanceof Error ? error.message : String(error), status: 400 };
56
36
  }
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 });
37
+ // Internal cron/catch-up are trusted to fire on their own occurrence; the
38
+ // HTTP adapter validates the public grace window so an external clock cannot
39
+ // back-fill history.
40
+ if (triggerSource === 'http' || triggerSource === 'manual') {
41
+ const window = (0, OccurrenceResolver_1.checkOccurrenceWindow)(occurrence, at, graceMin);
42
+ if (!window.ok) {
43
+ return { error: window.error, status: window.status };
44
+ }
72
45
  }
73
- return out;
46
+ return {
47
+ context: {
48
+ slotId: occurrence.slotId,
49
+ scheduleId: occurrence.scheduleId,
50
+ occurrenceAt: occurrence.occurrenceAt.getTime(),
51
+ occurrenceDate: occurrence.occurrenceDate,
52
+ occurrenceLabel: occurrence.occurrenceLabel,
53
+ timezone: occurrence.timezone,
54
+ triggerSource: occurrence.triggerSource,
55
+ slotName: requestedSlotName?.trim() || occurrence.occurrenceLabel,
56
+ slotDate: occurrence.occurrenceDate,
57
+ },
58
+ };
74
59
  }
75
- /** Open (or resume) a slot and return whether the whole slot is already done. */
76
- begin(slot, schedule) {
60
+ /**
61
+ * Open (or resume) an occurrence and snapshot its target membership on first
62
+ * creation. A later config reload cannot add/remove cells for this occurrence.
63
+ */
64
+ begin(slot, schedule, targets) {
65
+ const targetIds = targets.map((t) => t.id).filter((id) => Boolean(id));
77
66
  const { slot: slotRec, created } = this.database.slots.getOrCreateSlot(slot.slotId, {
67
+ scheduleId: slot.scheduleId,
68
+ occurrenceAt: slot.occurrenceAt,
69
+ occurrenceDate: slot.occurrenceDate,
70
+ occurrenceLabel: slot.occurrenceLabel,
71
+ timezone: slot.timezone,
72
+ targetIds,
73
+ triggerSource: slot.triggerSource,
78
74
  slotDate: slot.slotDate,
79
75
  slotName: slot.slotName,
80
- scheduleId: schedule.id,
81
- triggerSource: slot.triggerSource,
82
76
  });
83
- if (created)
84
- logger_1.logger.info('Slot started', { slot: slot.slotId, schedule: schedule.id });
85
- else
77
+ if (created) {
78
+ // Freeze membership: materialize one cell per target id from the snapshot.
79
+ const workTypeById = new Map(targets.map((t) => [t.id, t.type ?? 'unknown']));
80
+ this.database.slots.materializeCells(slot.slotId, targetIds, (id) => workTypeById.get(id) ?? 'unknown');
81
+ logger_1.logger.info('Slot started', { slot: slot.slotId, schedule: schedule.id, targets: targetIds.length });
82
+ }
83
+ else {
86
84
  logger_1.logger.info('Slot resumed (duplicate trigger or restart)', { slot: slot.slotId, status: slotRec.status });
85
+ }
87
86
  if (slotRec.status === 'success' || slotRec.status === 'partial') {
88
87
  return { slotRec, alreadyCompleted: true };
89
88
  }
90
89
  this.database.slots.markSlotStatus(slot.slotId, 'running');
91
90
  return { slotRec, alreadyCompleted: false };
92
91
  }
92
+ /**
93
+ * The targets that still need to run for this occurrence. Membership comes
94
+ * from the materialized snapshot (stable), intersected with the targets the
95
+ * caller currently knows about; terminal cells are skipped on resume.
96
+ */
97
+ pendingTargets(slotId, targets) {
98
+ const membership = new Set(this.database.slots.getSlotTargetIds(slotId));
99
+ const out = [];
100
+ for (const target of targets) {
101
+ if (!target.id)
102
+ continue;
103
+ if (membership.size > 0 && !membership.has(target.id))
104
+ continue; // config reload: not part of this occurrence
105
+ const cell = this.database.slots.getCell(slotId, target.id);
106
+ if (!cell)
107
+ continue;
108
+ if (cell.status === 'submitted' || cell.status === 'no_candidate')
109
+ continue;
110
+ out.push({ target, cell });
111
+ }
112
+ return out;
113
+ }
93
114
  /** Lock the selected work for a cell (first selection wins; retries keep it). */
94
115
  lockWork(slotId, targetId, workId, workType) {
95
116
  this.database.slots.ensureCell(slotId, targetId, workType);
@@ -104,16 +125,17 @@ class SlotCoordinator {
104
125
  return; // never downgrade a delivered cell
105
126
  this.database.slots.setCellStatus(slotId, targetId, status, error);
106
127
  }
107
- /** Roll cell results up into the slot status and log a readable summary. */
128
+ /** Roll cell results up into the slot status (one place computes the aggregate). */
108
129
  finish(slot, schedule, targets) {
109
- for (const t of targets) {
110
- if (!t.id)
130
+ const membership = this.database.slots.getSlotTargetIds(slot.slotId);
131
+ const ids = membership.length > 0 ? membership : targets.map((t) => t.id).filter(Boolean);
132
+ for (const targetId of ids) {
133
+ const cell = this.database.slots.getCell(slot.slotId, targetId);
134
+ if (!cell)
111
135
  continue;
112
- const cell = this.database.slots.getCell(slot.slotId, t.id);
113
- if (!cell || cell.status === 'pending' || cell.status === 'selected') {
136
+ if (cell.status === 'pending' || cell.status === 'selected') {
114
137
  // 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');
138
+ this.database.slots.setCellStatus(slot.slotId, targetId, 'failed', cell.lastError ?? 'target did not complete');
117
139
  }
118
140
  }
119
141
  const status = this.database.slots.deriveSlotStatus(slot.slotId);
@@ -147,4 +169,8 @@ class SlotCoordinator {
147
169
  }
148
170
  }
149
171
  exports.SlotCoordinator = SlotCoordinator;
172
+ /** Resolve the timezone a schedule runs in (never the server's local tz). */
173
+ function timezoneForSchedule(schedule, config) {
174
+ return (0, OccurrenceResolver_1.scheduleTimezone)(schedule, config.scheduler?.timezone);
175
+ }
150
176
  //# sourceMappingURL=SlotCoordinator.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"SlotCoordinator.js","sourceRoot":"","sources":["../../src/scheduler/SlotCoordinator.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"SlotCoordinator.js","sourceRoot":"","sources":["../../src/scheduler/SlotCoordinator.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;CAyKvB"}
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;CA8MvB"}
@@ -78,13 +78,24 @@ class DatabaseMigration {
78
78
  // Schedule Slots: one business batch (e.g. 2026-09-08:morning). A slot
79
79
  // groups one run of each enabled target (a "cell"). External triggers
80
80
  // and restarts converge on the SAME slot row instead of re-running.
81
+ //
82
+ // A Slot is one durable execution occurrence of a Schedule. Its id is
83
+ // schedule-scoped (`<scheduleId>@<occurrenceStamp>`); occurrence_at is
84
+ // the canonical scheduled fire time in the schedule's own timezone.
85
+ // target_ids snapshots the membership materialized at first run so a
86
+ // later config reload cannot mutate an in-flight occurrence.
81
87
  `CREATE TABLE IF NOT EXISTS schedule_slots (
82
88
  id TEXT PRIMARY KEY,
83
- slot_date TEXT NOT NULL,
84
- slot_name TEXT NOT NULL,
85
89
  schedule_id TEXT NOT NULL,
90
+ occurrence_at INTEGER,
91
+ occurrence_date TEXT NOT NULL DEFAULT '',
92
+ occurrence_label TEXT NOT NULL DEFAULT '',
93
+ timezone TEXT NOT NULL DEFAULT 'UTC',
94
+ target_ids TEXT,
86
95
  status TEXT NOT NULL DEFAULT 'pending',
87
96
  trigger_source TEXT,
97
+ slot_date TEXT NOT NULL DEFAULT '',
98
+ slot_name TEXT NOT NULL DEFAULT '',
88
99
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
89
100
  started_at DATETIME,
90
101
  completed_at DATETIME,
@@ -108,6 +119,32 @@ class DatabaseMigration {
108
119
  UNIQUE(slot_id, target_id)
109
120
  )`,
110
121
  ];
122
+ // Phase 1: create tables (idempotent). Must run before any PRAGMA-based
123
+ // column check, otherwise a fresh DB would report the table as missing and
124
+ // both CREATE and ADD COLUMN would create the same column.
125
+ const createTables = this.db.transaction((stmts) => {
126
+ for (const sql of stmts) {
127
+ this.db.prepare(sql).run();
128
+ }
129
+ });
130
+ createTables(migrations);
131
+ // Phase 2: additive column migrations for databases created before the
132
+ // canonical occurrence model. The table now exists, so PRAGMA reports the
133
+ // true current columns; ALTER only the ones missing on upgraded DBs (fresh
134
+ // DBs already have them from the CREATE above and skip these).
135
+ const slotCols = this.db.prepare(`PRAGMA table_info(schedule_slots)`).all().map((c) => c.name);
136
+ const slotColumnMigrations = {
137
+ occurrence_at: 'ALTER TABLE schedule_slots ADD COLUMN occurrence_at INTEGER',
138
+ occurrence_date: `ALTER TABLE schedule_slots ADD COLUMN occurrence_date TEXT NOT NULL DEFAULT ''`,
139
+ occurrence_label: `ALTER TABLE schedule_slots ADD COLUMN occurrence_label TEXT NOT NULL DEFAULT ''`,
140
+ timezone: `ALTER TABLE schedule_slots ADD COLUMN timezone TEXT NOT NULL DEFAULT 'UTC'`,
141
+ target_ids: 'ALTER TABLE schedule_slots ADD COLUMN target_ids TEXT',
142
+ };
143
+ const columnAlters = [];
144
+ for (const [col, sql] of Object.entries(slotColumnMigrations)) {
145
+ if (!slotCols.includes(col))
146
+ columnAlters.push(sql);
147
+ }
111
148
  // Create indexes for better query performance
112
149
  const indexes = [
113
150
  `CREATE INDEX IF NOT EXISTS idx_downloads_pixiv_id_type ON downloads(pixiv_id, type)`,
@@ -120,16 +157,16 @@ class DatabaseMigration {
120
157
  `CREATE INDEX IF NOT EXISTS idx_task_history_task_id ON task_history(task_id)`,
121
158
  `CREATE INDEX IF NOT EXISTS idx_task_history_status ON task_history(status)`,
122
159
  `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)`,
160
+ `CREATE INDEX IF NOT EXISTS idx_slots_schedule_occ ON schedule_slots(schedule_id, occurrence_at DESC)`,
124
161
  `CREATE INDEX IF NOT EXISTS idx_slot_items_slot ON schedule_slot_items(slot_id)`,
125
162
  `CREATE INDEX IF NOT EXISTS idx_slot_items_work ON schedule_slot_items(work_id, work_type)`,
126
163
  ];
127
- const transaction = this.db.transaction((stmts) => {
164
+ const postMigration = this.db.transaction((stmts) => {
128
165
  for (const sql of stmts) {
129
166
  this.db.prepare(sql).run();
130
167
  }
131
168
  });
132
- transaction([...migrations, ...indexes]);
169
+ postMigration([...columnAlters, ...indexes]);
133
170
  // Add is_active column to config_history if it doesn't exist
134
171
  try {
135
172
  // Check if column exists by querying pragma_table_info
@@ -1 +1 @@
1
- {"version":3,"file":"DatabaseMigration.js","sourceRoot":"","sources":["../../src/storage/DatabaseMigration.ts"],"names":[],"mappings":"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"}
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;gBACJ,uEAAuE;gBACvE,sEAAsE;gBACtE,oEAAoE;gBACpE,EAAE;gBACF,sEAAsE;gBACtE,uEAAuE;gBACvE,oEAAoE;gBACpE,qEAAqE;gBACrE,6DAA6D;gBAC7D;;;;;;;;;;;;;;;;YAgBI;gBACJ,sEAAsE;gBACtE,sEAAsE;gBACtE,mEAAmE;gBACnE;;;;;;;;;;;;;YAaI;aACL,CAAC;YAEF,wEAAwE;YACxE,2EAA2E;YAC3E,2DAA2D;YAC3D,MAAM,YAAY,GAAG,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,KAAe,EAAE,EAAE;gBAC3D,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;oBACxB,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;gBAC7B,CAAC;YACH,CAAC,CAAC,CAAC;YACH,YAAY,CAAC,UAAU,CAAC,CAAC;YAEzB,uEAAuE;YACvE,0EAA0E;YAC1E,2EAA2E;YAC3E,+DAA+D;YAC/D,MAAM,QAAQ,GAAI,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,mCAAmC,CAAC,CAAC,GAAG,EAA8B,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YAC5H,MAAM,oBAAoB,GAA2B;gBACnD,aAAa,EAAE,6DAA6D;gBAC5E,eAAe,EAAE,gFAAgF;gBACjG,gBAAgB,EAAE,iFAAiF;gBACnG,QAAQ,EAAE,4EAA4E;gBACtF,UAAU,EAAE,uDAAuD;aACpE,CAAC;YACF,MAAM,YAAY,GAAa,EAAE,CAAC;YAClC,KAAK,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,oBAAoB,CAAC,EAAE,CAAC;gBAC9D,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC;oBAAE,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACtD,CAAC;YAED,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;gBACpF,sGAAsG;gBACtG,gFAAgF;gBAChF,2FAA2F;aAC5F,CAAC;YAEF,MAAM,aAAa,GAAG,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,KAAe,EAAE,EAAE;gBAC5D,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;oBACxB,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;gBAC7B,CAAC;YACH,CAAC,CAAC,CAAC;YACH,aAAa,CAAC,CAAC,GAAG,YAAY,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC;YAE7C,6DAA6D;YAC7D,IAAI,CAAC;gBACH,uDAAuD;gBACvD,MAAM,SAAS,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,mCAAmC,CAAC,CAAC,GAAG,EAA6B,CAAC;gBACxG,MAAM,iBAAiB,GAAG,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC;gBAE1E,IAAI,CAAC,iBAAiB,EAAE,CAAC;oBACvB,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,mEAAmE,CAAC,CAAC,GAAG,EAAE,CAAC;oBAC3F,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,sFAAsF,CAAC,CAAC,GAAG,EAAE,CAAC;gBAChH,CAAC;YACH,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,2CAA2C;gBAC3C,oEAAoE;gBACpE,eAAM,CAAC,IAAI,CAAC,oDAAoD,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;YAC/E,CAAC;YAED,yEAAyE;YACzE,IAAI,CAAC;gBACH,MAAM,SAAS,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,yCAAyC,CAAC,CAAC,GAAG,EAA6B,CAAC;gBAC9G,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,aAAa,CAAC,EAAE,CAAC;oBACvD,IAAI,CAAC,EAAE,CAAC,OAAO,CACb,yFAAyF,CAC1F,CAAC,GAAG,EAAE,CAAC;gBACV,CAAC;gBACD,IAAI,CAAC,EAAE,CAAC,OAAO,CACb,qHAAqH,CACtH,CAAC,GAAG,EAAE,CAAC;YACV,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,eAAM,CAAC,IAAI,CAAC,wDAAwD,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;YACnF,CAAC;YAED,0EAA0E;YAC1E,IAAI,CAAC;gBACH,MAAM,SAAS,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,iCAAiC,CAAC,CAAC,GAAG,EAA6B,CAAC;gBACtG,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBAC3B,2EAA2E;oBAC3E,8BAA8B;oBAC9B,eAAM,CAAC,KAAK,CAAC,kDAAkD,CAAC,CAAC;gBACnE,CAAC;YACH,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,eAAM,CAAC,IAAI,CAAC,wDAAwD,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;YACnF,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,sBAAa,CACrB,mCAAmC,EACnC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAC3C,CAAC;QACJ,CAAC;IACH,CAAC;CACF;AApND,8CAoNC"}
@@ -3,11 +3,21 @@ export type SlotStatus = 'pending' | 'running' | 'success' | 'partial' | 'failed
3
3
  export type CellStatus = 'pending' | 'selected' | 'submitted' | 'no_candidate' | 'failed';
4
4
  export interface SlotRecord {
5
5
  id: string;
6
- slotDate: string;
7
- slotName: string;
6
+ /** Schedule this occurrence belongs to (id is already schedule-scoped). */
8
7
  scheduleId: string;
8
+ /** Canonical scheduled fire time (epoch ms, UTC); null for legacy rows. */
9
+ occurrenceAt: number | null;
10
+ /** Schedule date (YYYY-MM-DD) in the schedule timezone — display only. */
11
+ occurrenceDate: string;
12
+ /** Wall-clock time-of-day label in tz, e.g. "10:00" — display only. */
13
+ occurrenceLabel: string;
14
+ timezone: string;
15
+ /** Materialized target membership snapshot (JSON array of target ids). */
16
+ targetIds: string[];
9
17
  status: SlotStatus;
10
18
  triggerSource: string | null;
19
+ slotDate: string;
20
+ slotName: string;
11
21
  createdAt: string;
12
22
  startedAt: string | null;
13
23
  completedAt: string | null;
@@ -37,26 +47,40 @@ export interface SlotItemRecord {
37
47
  */
38
48
  export declare class SlotRepository extends BaseRepository {
39
49
  /**
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).
50
+ * Fetch an existing slot or create it. On creation the schedule's target
51
+ * membership is snapshotted (target_ids); a later config reload never mutates
52
+ * this occurrence. Returns `created:false` when the id already existed so the
53
+ * caller resumes rather than restarting.
43
54
  */
44
55
  getOrCreateSlot(id: string, data: {
45
- slotDate: string;
46
- slotName: string;
47
56
  scheduleId: string;
57
+ occurrenceAt?: number | null;
58
+ occurrenceDate?: string;
59
+ occurrenceLabel?: string;
60
+ timezone?: string;
61
+ targetIds: string[];
48
62
  triggerSource?: string;
63
+ slotDate?: string;
64
+ slotName?: string;
49
65
  }): {
50
66
  slot: SlotRecord;
51
67
  created: boolean;
52
68
  };
53
69
  getSlot(id: string): SlotRecord | null;
54
- getSlotsForDate(slotDate: string): SlotRecord[];
70
+ /** Target ids materialized for a slot (stable membership; falls back to []). */
71
+ getSlotTargetIds(id: string): string[];
55
72
  getRecentSlots(limit?: number): SlotRecord[];
56
73
  markSlotStatus(id: string, status: SlotStatus, error?: string): void;
57
74
  /** All cells for a slot (one per target). */
58
75
  getCells(slotId: string): SlotItemRecord[];
59
76
  getCell(slotId: string, targetId: string): SlotItemRecord | null;
77
+ /**
78
+ * Ensure a cell exists for every target id in the slot's materialized
79
+ * membership. The cell set is fixed at first materialization (the snapshot in
80
+ * schedule_slots.target_ids); a config reload cannot add/remove cells here.
81
+ * Returns the authoritative target ids for this occurrence.
82
+ */
83
+ materializeCells(slotId: string, targetIds: string[], workTypeByTarget: (id: string) => string): string[];
60
84
  /** Create the cell row if it does not exist (idempotent). */
61
85
  ensureCell(slotId: string, targetId: string, workType: string): SlotItemRecord;
62
86
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"SlotRepository.d.ts","sourceRoot":"","sources":["../../../src/storage/repositories/SlotRepository.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"SlotRepository.d.ts","sourceRoot":"","sources":["../../../src/storage/repositories/SlotRepository.ts"],"names":[],"mappings":"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"}
@@ -13,20 +13,30 @@ const BaseRepository_1 = require("./BaseRepository");
13
13
  */
14
14
  class SlotRepository extends BaseRepository_1.BaseRepository {
15
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).
16
+ * Fetch an existing slot or create it. On creation the schedule's target
17
+ * membership is snapshotted (target_ids); a later config reload never mutates
18
+ * this occurrence. Returns `created:false` when the id already existed so the
19
+ * caller resumes rather than restarting.
19
20
  */
20
21
  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)
22
+ const insert = this.db.prepare(`INSERT INTO schedule_slots
23
+ (id, schedule_id, occurrence_at, occurrence_date, occurrence_label, timezone, target_ids,
24
+ status, trigger_source, slot_date, slot_name)
25
+ VALUES
26
+ (@id, @scheduleId, @occurrenceAt, @occurrenceDate, @occurrenceLabel, @timezone, @targetIds,
27
+ 'pending', @triggerSource, @slotDate, @slotName)
23
28
  ON CONFLICT(id) DO NOTHING`);
24
29
  const info = insert.run({
25
30
  id,
26
- slotDate: data.slotDate,
27
- slotName: data.slotName,
28
31
  scheduleId: data.scheduleId,
32
+ occurrenceAt: data.occurrenceAt ?? null,
33
+ occurrenceDate: data.occurrenceDate ?? '',
34
+ occurrenceLabel: data.occurrenceLabel ?? '',
35
+ timezone: data.timezone ?? 'UTC',
36
+ targetIds: JSON.stringify(data.targetIds),
29
37
  triggerSource: data.triggerSource ?? null,
38
+ slotDate: data.slotDate ?? data.occurrenceDate ?? '',
39
+ slotName: data.slotName ?? '',
30
40
  });
31
41
  const created = info.changes > 0;
32
42
  return { slot: this.getSlot(id), created };
@@ -35,15 +45,22 @@ class SlotRepository extends BaseRepository_1.BaseRepository {
35
45
  const row = this.db.prepare(`SELECT * FROM schedule_slots WHERE id = ?`).get(id);
36
46
  return row ? this.toSlot(row) : null;
37
47
  }
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));
48
+ /** Target ids materialized for a slot (stable membership; falls back to []). */
49
+ getSlotTargetIds(id) {
50
+ const row = this.db.prepare(`SELECT target_ids FROM schedule_slots WHERE id = ?`).get(id);
51
+ if (!row?.target_ids)
52
+ return [];
53
+ try {
54
+ const parsed = JSON.parse(row.target_ids);
55
+ return Array.isArray(parsed) ? parsed.map(String) : [];
56
+ }
57
+ catch {
58
+ return [];
59
+ }
43
60
  }
44
61
  getRecentSlots(limit = 14) {
45
62
  const rows = this.db
46
- .prepare(`SELECT * FROM schedule_slots ORDER BY id DESC LIMIT ?`)
63
+ .prepare(`SELECT * FROM schedule_slots ORDER BY COALESCE(occurrence_at, 0) DESC, id DESC LIMIT ?`)
47
64
  .all(limit);
48
65
  return rows.map((r) => this.toSlot(r));
49
66
  }
@@ -71,6 +88,29 @@ class SlotRepository extends BaseRepository_1.BaseRepository {
71
88
  .get(slotId, targetId);
72
89
  return row ? this.toItem(row) : null;
73
90
  }
91
+ /**
92
+ * Ensure a cell exists for every target id in the slot's materialized
93
+ * membership. The cell set is fixed at first materialization (the snapshot in
94
+ * schedule_slots.target_ids); a config reload cannot add/remove cells here.
95
+ * Returns the authoritative target ids for this occurrence.
96
+ */
97
+ materializeCells(slotId, targetIds, workTypeByTarget) {
98
+ // The frozen snapshot (schedule_slots.target_ids) is the authority for which
99
+ // cells belong to this occurrence. Intersect with the requested ids so a
100
+ // later config reload can never materialize a cell outside the snapshot.
101
+ const snapshot = new Set(this.getSlotTargetIds(slotId));
102
+ const authorized = snapshot.size > 0 ? targetIds.filter((id) => snapshot.has(id)) : targetIds;
103
+ const insert = this.db.prepare(`INSERT INTO schedule_slot_items (slot_id, target_id, work_type, status)
104
+ VALUES (@slotId, @targetId, @workType, 'pending')
105
+ ON CONFLICT(slot_id, target_id) DO NOTHING`);
106
+ const tx = this.db.transaction((ids) => {
107
+ for (const targetId of ids) {
108
+ insert.run({ slotId, targetId, workType: workTypeByTarget(targetId) || 'unknown' });
109
+ }
110
+ });
111
+ tx(authorized);
112
+ return authorized;
113
+ }
74
114
  /** Create the cell row if it does not exist (idempotent). */
75
115
  ensureCell(slotId, targetId, workType) {
76
116
  this.db
@@ -137,13 +177,27 @@ class SlotRepository extends BaseRepository_1.BaseRepository {
137
177
  return 'failed';
138
178
  }
139
179
  toSlot(row) {
180
+ let targetIds = [];
181
+ try {
182
+ const parsed = row.target_ids ? JSON.parse(row.target_ids) : [];
183
+ if (Array.isArray(parsed))
184
+ targetIds = parsed.map(String);
185
+ }
186
+ catch {
187
+ targetIds = [];
188
+ }
140
189
  return {
141
190
  id: row.id,
142
- slotDate: row.slot_date,
143
- slotName: row.slot_name,
144
191
  scheduleId: row.schedule_id,
192
+ occurrenceAt: row.occurrence_at ?? null,
193
+ occurrenceDate: row.occurrence_date ?? '',
194
+ occurrenceLabel: row.occurrence_label ?? '',
195
+ timezone: row.timezone ?? 'UTC',
196
+ targetIds,
145
197
  status: row.status,
146
198
  triggerSource: row.trigger_source,
199
+ slotDate: row.slot_date ?? '',
200
+ slotName: row.slot_name ?? '',
147
201
  createdAt: row.created_at,
148
202
  startedAt: row.started_at,
149
203
  completedAt: row.completed_at,
@@ -1 +1 @@
1
- {"version":3,"file":"SlotRepository.js","sourceRoot":"","sources":["../../../src/storage/repositories/SlotRepository.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"SlotRepository.js","sourceRoot":"","sources":["../../../src/storage/repositories/SlotRepository.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "type": "commonjs",
3
3
  "name": "pixivflow-webui-backend",
4
- "version": "2.11.0",
4
+ "version": "2.12.1",
5
5
  "description": "PixivFlow WebUI Backend - CommonJS module"
6
6
  }