pixivflow 2.19.0 → 2.19.2

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.
@@ -135,7 +135,7 @@ class ExecuteSlotCommand extends Command_1.BaseCommand {
135
135
  (0, runDiagnostics_1.recordRunError)(outcome.error);
136
136
  },
137
137
  ...(excludedWorkIds ? { excludedWorkIds } : {}),
138
- }), timeoutMs, () => runtime.cancelActive(`batch timeout after ${timeoutMs}ms`), `slot ${slotId}`);
138
+ }), timeoutMs, () => runtime.cancelActive(`batch timeout after ${timeoutMs}ms`, 'timeout'), `slot ${slotId}`);
139
139
  // Bounded drain: deliveries created by this run get one chance to confirm
140
140
  // before we report. Rows that cannot finish now stay durable and are
141
141
  // resolved by the control plane's reconciliation, never by a blind resend.
@@ -57,7 +57,9 @@ class SchedulerCommand extends Command_1.BaseCommand {
57
57
  telemetry: {
58
58
  beginRun: () => runtime.database.getOverviewStats().totalDownloads,
59
59
  endRun: () => runtime.database.getOverviewStats().totalDownloads,
60
- requestCancel: (reason) => runtime.cancelActive(reason),
60
+ // `timeout`: the daemon stays alive, so the run's Slot must be taken
61
+ // terminal (the abort path does that) instead of staying recoverable.
62
+ requestCancel: (reason) => runtime.cancelActive(reason, 'timeout'),
61
63
  },
62
64
  });
63
65
  const status = manager.start(runtime.config);
@@ -53,7 +53,7 @@ class SchedulerRunOnceCommand extends Command_1.BaseCommand {
53
53
  // adhoc: a manual/operator run executes the download plan but never
54
54
  // opens a scheduled Slot, so it can neither mark a scheduled
55
55
  // occurrence complete nor be resumed as one. Explicit replacement.
56
- runtime.runJob(runtime.config, plan, { adhoc: true, triggerSource: 'manual', onlyTarget: targetFilter }), timeoutMs, () => runtime.cancelActive(`run timeout after ${timeoutMs}ms`), `plan ${plan.id}`);
56
+ runtime.runJob(runtime.config, plan, { adhoc: true, triggerSource: 'manual', onlyTarget: targetFilter }), timeoutMs, () => runtime.cancelActive(`run timeout after ${timeoutMs}ms`, 'timeout'), `plan ${plan.id}`);
57
57
  }
58
58
  // Flush deliveries/notifications created by this one-shot before exit.
59
59
  // A bounded drain: durable rows survive if they cannot finish now and the
@@ -51,6 +51,29 @@ export type ExecutionMode = (typeof EXECUTION_MODES)[number];
51
51
  export declare function withDeliveryMode<T extends {
52
52
  delivery?: unknown;
53
53
  }>(targets: T[], mode: ExecutionMode | undefined): T[];
54
+ /**
55
+ * Who asked for the cancellation, which decides whether the abandoned Slot is
56
+ * allowed to stay recoverable.
57
+ *
58
+ * - `timeout`: a watchdog inside this process (scheduler timeout, run-once or
59
+ * execute-slot bound). The process stays up, so nothing will ever finish the
60
+ * Slot — it must be terminalised, or the recovery sweep re-dispatches the
61
+ * same occurrence on every tick forever.
62
+ * - `shutdown`: the process is going away. The Slot is deliberately left
63
+ * non-terminal so recovery resumes the same occurrence after restart; no
64
+ * worker survives to duplicate it.
65
+ */
66
+ export type CancelOrigin = 'timeout' | 'shutdown';
67
+ /**
68
+ * Decide a scheduled run's Slot fate when `runAllTargets()` aborts abnormally
69
+ * instead of reporting per-target failures.
70
+ *
71
+ * Returning `false` leaves the Slot recoverable, which is only correct when the
72
+ * process is genuinely going away — because `recoverableSlots()` treats a
73
+ * released/NULL lease as "recorded but never claimed", so a live process that
74
+ * merely drops its lease is re-dispatched on every recovery tick, forever.
75
+ */
76
+ export declare function shouldTerminaliseAbortedSlot(origin: CancelOrigin | null, slotAbandoned: boolean): boolean;
54
77
  export interface SchedulerRuntime {
55
78
  config: StandaloneConfig;
56
79
  database: Database;
@@ -59,8 +82,14 @@ export interface SchedulerRuntime {
59
82
  tokenMaintenance: ReturnType<typeof createTokenMaintenanceService>;
60
83
  /** Run one schedule's enabled targets once (the same job the cron fires). */
61
84
  runJob(snapshot: StandaloneConfig, schedule: ScheduleConfig, options?: RunJobOptions): Promise<void>;
62
- /** Cancel the in-flight download plan, if any. */
63
- cancelActive(reason: string): void;
85
+ /**
86
+ * Cancel the in-flight download plan, if any holding a Slot.
87
+ *
88
+ * `origin` states whether this process is staying alive (`timeout`: the
89
+ * run is finished and its Slot must be terminalised) or going away
90
+ * (`shutdown`: leave the Slot non-terminal so recovery resumes it).
91
+ */
92
+ cancelActive(reason: string, origin?: CancelOrigin): void;
64
93
  /**
65
94
  * The active run never settled after its timeout and drain window. Stop
66
95
  * renewing its lease and take its Slot terminal so recovery cannot re-dispatch
@@ -43,6 +43,7 @@ var __importStar = (this && this.__importStar) || (function () {
43
43
  Object.defineProperty(exports, "__esModule", { value: true });
44
44
  exports.EXECUTION_MODES = void 0;
45
45
  exports.withDeliveryMode = withDeliveryMode;
46
+ exports.shouldTerminaliseAbortedSlot = shouldTerminaliseAbortedSlot;
46
47
  exports.notifyScheduleFailure = notifyScheduleFailure;
47
48
  exports.createSchedulerRuntime = createSchedulerRuntime;
48
49
  exports.runWithTimeout = runWithTimeout;
@@ -74,6 +75,23 @@ function withDeliveryMode(targets, mode) {
74
75
  return targets;
75
76
  return targets.map((target) => (target.delivery ? { ...target, delivery: undefined } : target));
76
77
  }
78
+ /**
79
+ * Decide a scheduled run's Slot fate when `runAllTargets()` aborts abnormally
80
+ * instead of reporting per-target failures.
81
+ *
82
+ * Returning `false` leaves the Slot recoverable, which is only correct when the
83
+ * process is genuinely going away — because `recoverableSlots()` treats a
84
+ * released/NULL lease as "recorded but never claimed", so a live process that
85
+ * merely drops its lease is re-dispatched on every recovery tick, forever.
86
+ */
87
+ function shouldTerminaliseAbortedSlot(origin, slotAbandoned) {
88
+ // The abandon path already wrote a terminal `failed`; rolling up again would
89
+ // only overwrite it when the wedged job finally settles.
90
+ if (slotAbandoned)
91
+ return false;
92
+ // Shutdown is not a failure: recovery is meant to resume this occurrence.
93
+ return origin !== 'shutdown';
94
+ }
77
95
  /**
78
96
  * Open the pixivflow database with a startup integrity check. A structurally
79
97
  * corrupt file (quick_check failure) is isolated aside and replaced with a
@@ -209,6 +227,13 @@ async function createSchedulerRuntime(configPathArg) {
209
227
  * Set while a lease is held and cleared as soon as it is released.
210
228
  */
211
229
  let activeLeaseHooks = null;
230
+ /**
231
+ * Why the in-flight run was cancelled, if it was. This is what lets the abort
232
+ * path tell a CRASH (nothing runs here — the process is gone) apart from an
233
+ * ABANDONMENT (this process is alive and will never touch the Slot again).
234
+ * `null` while no cancellation has been requested for the current run.
235
+ */
236
+ let activeAbortOrigin = null;
212
237
  // Independently-pumped durable outbox (content + notifications). Started in
213
238
  // the long-running scheduler daemon; run-once drains explicitly before exit.
214
239
  const deliveryDispatcher = new DeliveryDispatcher_1.DeliveryDispatcher(config.delivery, buildProxyUrl(config.network));
@@ -311,6 +336,9 @@ async function createSchedulerRuntime(configPathArg) {
311
336
  // Only the process that actually owns the lease may report the slot as
312
337
  // running; the accepting adapter records it as pending instead.
313
338
  coordinator.markRunning(activeSlot.slotId);
339
+ // This run owns the Slot now: any cancellation recorded against a previous
340
+ // run must not decide how THIS run's abort is handled.
341
+ activeAbortOrigin = null;
314
342
  let cancelled = false;
315
343
  const heartbeat = setInterval(() => {
316
344
  // A cancelled/timed-out run must stop renewing its lease. An infinitely
@@ -451,9 +479,24 @@ async function createSchedulerRuntime(configPathArg) {
451
479
  }
452
480
  catch (error) {
453
481
  if (!slotCtx || !(error instanceof Error) || !/^All \d+ target\(s\) failed\./.test(error.message)) {
454
- // Abnormal abort: no roll-up is possible, so hand the slot back now
455
- // instead of holding it until the lease TTL expires. Recovery sees a
456
- // non-terminal slot with no live lease and resumes the SAME occurrence.
482
+ // Abnormal abort. Two very different situations land here, and treating
483
+ // them as one is what produced the production loop:
484
+ //
485
+ // - this process cancelled itself (scheduler timeout / watchdog) and is
486
+ // still alive. It will never touch the Slot again, so releasing the
487
+ // lease while leaving the status `running` makes the Slot look exactly
488
+ // like a crashed worker: `recoverableSlots()` matches a NULL lease on
489
+ // purpose (its "recorded but never claimed" case), so the recovery
490
+ // sweep re-dispatches the SAME occurrence on every tick, forever.
491
+ // Terminalise it instead: the occurrence is finished, and failed.
492
+ //
493
+ // - the process is going away (`shutdown`). Deliberately leave the Slot
494
+ // non-terminal so recovery resumes the same occurrence after restart.
495
+ if (slotCtx && shouldTerminaliseAbortedSlot(activeAbortOrigin, slotAbandoned)) {
496
+ coordinator.finish(slotCtx, schedule, targets);
497
+ }
498
+ // Hand the lease back either way: a terminal Slot cannot be re-dispatched,
499
+ // and a non-terminal one (shutdown) must not wait for its TTL to expire.
457
500
  releaseLease?.();
458
501
  throw error;
459
502
  }
@@ -491,12 +534,13 @@ async function createSchedulerRuntime(configPathArg) {
491
534
  });
492
535
  logger_1.logger.info('='.repeat(60));
493
536
  };
494
- const cancelActive = (reason) => {
537
+ const cancelActive = (reason, origin = 'timeout') => {
538
+ activeAbortOrigin = origin;
495
539
  activeDownloadManager?.cancel(reason);
496
540
  // Scheduler timeout / process shutdown also stop the lease heartbeat. The run
497
541
  // is on its way out (or about to be killed with the process), so it must not
498
- // keep the slot locked while it unwinds. A shutdown deliberately leaves the
499
- // slot NON-terminal: recovery resumes the same occurrence after restart.
542
+ // keep the slot locked while it unwinds. Whether the Slot is then terminalised
543
+ // or left recoverable is decided by `origin` in the abort path of runJob.
500
544
  activeLeaseHooks?.stopHeartbeat();
501
545
  };
502
546
  const abandonActiveRun = (reason) => {
@@ -507,7 +551,7 @@ async function createSchedulerRuntime(configPathArg) {
507
551
  };
508
552
  const close = () => {
509
553
  outboxWorker.stop();
510
- cancelActive('process shutdown');
554
+ cancelActive('process shutdown', 'shutdown');
511
555
  if (tokenMaintenance) {
512
556
  tokenMaintenance.stop();
513
557
  }
@@ -78,6 +78,8 @@ export declare class OutboxWorker {
78
78
  private recordMediaFallback;
79
79
  private recordEvent;
80
80
  private process;
81
+ /** Terminal delivery failure: audit it, release the delivery, notify the hooks. */
82
+ private deadLetter;
81
83
  private handleDeliveryAck;
82
84
  private cleanup;
83
85
  }
@@ -245,24 +245,21 @@ class OutboxWorker {
245
245
  return 'done';
246
246
  }
247
247
  catch (error) {
248
- // Transport-level error (fetch threw) or ack-classified failure: retryable.
249
248
  const message = (0, redact_1.redactError)(error).slice(0, 1000);
250
249
  const { errorClass } = (0, errorClass_1.classifyError)(error);
250
+ // A local configuration error is deterministic: every attempt re-reads the
251
+ // same config, so retrying only parks the row in `retry_wait` until its
252
+ // attempt budget runs out. Dead-letter it now so it is visible instead.
253
+ if (errorClass === 'configuration_error') {
254
+ this.database.outbox.markDead(row.id, message);
255
+ this.deadLetter(row, `${message} (configuration error)`, errorClass);
256
+ return 'dead';
257
+ }
258
+ // Transport-level error (fetch threw) or ack-classified failure: retryable.
251
259
  const delay = backoffDelayMs(row.attempts + 1, this.retryBaseMs, this.retryMaxMs);
252
260
  const status = this.database.outbox.markRetry(row.id, Date.now() + delay, message);
253
261
  if (status === 'dead') {
254
- logger_1.logger.error('Outbox item dead after max attempts', { outboxId: row.id, kind: row.kind, error: message });
255
- this.recordEvent(row, {
256
- event: 'outbox.dead',
257
- errorClass,
258
- retryable: false,
259
- countsAsAttempt: 1,
260
- detail: { attempt: row.attempts + 1 },
261
- });
262
- this.onDead?.(row, message);
263
- if (row.deliveryId) {
264
- this.database.deliveries.recordAck(row.deliveryId, { status: 'failed', error: message });
265
- }
262
+ this.deadLetter(row, message, errorClass);
266
263
  }
267
264
  else {
268
265
  logger_1.logger.warn('Outbox item will retry', { outboxId: row.id, kind: row.kind, attempt: row.attempts + 1, delayMs: delay });
@@ -277,6 +274,21 @@ class OutboxWorker {
277
274
  return status;
278
275
  }
279
276
  }
277
+ /** Terminal delivery failure: audit it, release the delivery, notify the hooks. */
278
+ deadLetter(row, message, errorClass) {
279
+ logger_1.logger.error('Outbox item dead', { outboxId: row.id, kind: row.kind, errorClass, error: message });
280
+ this.recordEvent(row, {
281
+ event: 'outbox.dead',
282
+ errorClass,
283
+ retryable: false,
284
+ countsAsAttempt: 1,
285
+ detail: { attempt: row.attempts + 1 },
286
+ });
287
+ this.onDead?.(row, message);
288
+ if (row.deliveryId) {
289
+ this.database.deliveries.recordAck(row.deliveryId, { status: 'failed', error: message });
290
+ }
291
+ }
280
292
  async handleDeliveryAck(row, ack, payload) {
281
293
  if (!row.deliveryId)
282
294
  return;
@@ -2,7 +2,7 @@
2
2
  * Tiny pure error classification for delivery attempts.
3
3
  * Maps a thrown error / HTTP status to a stable audit category.
4
4
  */
5
- export type DeliveryErrorClass = 'dependency_not_ready' | 'network_timeout' | 'rate_limited' | 'remote_5xx' | 'remote_4xx' | 'invalid_payload' | 'telegram_send_failed' | 'duplicate' | 'internal_error';
5
+ export type DeliveryErrorClass = 'dependency_not_ready' | 'network_timeout' | 'rate_limited' | 'remote_5xx' | 'remote_4xx' | 'invalid_payload' | 'telegram_send_failed' | 'configuration_error' | 'duplicate' | 'internal_error';
6
6
  export interface ErrorClassification {
7
7
  errorClass: DeliveryErrorClass;
8
8
  retryable: boolean;
@@ -4,6 +4,13 @@ exports.classifyError = classifyError;
4
4
  /** Classify one failed delivery attempt from its thrown error and/or HTTP status. */
5
5
  function classifyError(error, status) {
6
6
  const message = error instanceof Error ? error.message : String(error ?? '');
7
+ // A local ConfigError is thrown before any network call and is deterministic:
8
+ // retrying re-reads the exact same config, so the attempt budget only parks the
9
+ // row in `retry_wait` for hours. Terminal for the outbox.
10
+ if (error?.name === 'ConfigError' ||
11
+ /does not configure|unsupported delivery target/i.test(message)) {
12
+ return { errorClass: 'configuration_error', retryable: false };
13
+ }
7
14
  // Explicit HTTP status wins when present.
8
15
  if (status === 429)
9
16
  return { errorClass: 'rate_limited', retryable: true };
@@ -16,6 +16,17 @@ export declare class NotificationPolicy {
16
16
  private readonly config;
17
17
  constructor(database: Database, config: StandaloneConfig);
18
18
  private targetName;
19
+ /**
20
+ * Delivery targets that can actually RECEIVE an operational notification.
21
+ *
22
+ * `delivery.target` names a SUBMISSION endpoint (multipart POST of a work).
23
+ * Only targets that also declare a `notificationUrl` accept notifications —
24
+ * the same rule `config/validation.ts` enforces for `noMatchPolicy.notify`
25
+ * and that `docs/CONFIG.md` documents. A submission endpoint without one
26
+ * rejects every notification, so enqueuing to it would only grow an outbox
27
+ * row that can never be delivered.
28
+ */
29
+ private notifiableTargets;
19
30
  /** Stable slot-scoped keys (two occurrences on one date never collide). */
20
31
  static keys: {
21
32
  noMatch: (slotId: string, targetId: string) => string;
@@ -21,6 +21,23 @@ class NotificationPolicy {
21
21
  targetName(target) {
22
22
  return target.delivery?.target?.trim() || null;
23
23
  }
24
+ /**
25
+ * Delivery targets that can actually RECEIVE an operational notification.
26
+ *
27
+ * `delivery.target` names a SUBMISSION endpoint (multipart POST of a work).
28
+ * Only targets that also declare a `notificationUrl` accept notifications —
29
+ * the same rule `config/validation.ts` enforces for `noMatchPolicy.notify`
30
+ * and that `docs/CONFIG.md` documents. A submission endpoint without one
31
+ * rejects every notification, so enqueuing to it would only grow an outbox
32
+ * row that can never be delivered.
33
+ */
34
+ notifiableTargets() {
35
+ const targets = this.config.delivery?.targets ?? {};
36
+ return new Set(Object.keys(targets).filter((name) => {
37
+ const target = targets[name];
38
+ return target?.type === 'httpMultipart' && Boolean(target.notificationUrl?.trim());
39
+ }));
40
+ }
24
41
  /** Stable slot-scoped keys (two occurrences on one date never collide). */
25
42
  static keys = {
26
43
  noMatch: (slotId, targetId) => `notification:${slotId}:${targetId}:no-candidate`,
@@ -32,6 +49,10 @@ class NotificationPolicy {
32
49
  const name = this.targetName(target);
33
50
  if (!name)
34
51
  return;
52
+ // No notifiable endpoint configured: drop the notification instead of
53
+ // enqueuing it against a submission target that will reject it forever.
54
+ if (!this.notifiableTargets().has(name))
55
+ return;
35
56
  const label = target.id || target.filterTag || target.tag || target.type;
36
57
  if (outcome.kind === 'no_candidate' && target.noMatchPolicy?.notify === true) {
37
58
  this.send(name, NotificationPolicy.keys.noMatch(slotId, target.id ?? label), [
@@ -53,11 +74,7 @@ class NotificationPolicy {
53
74
  }
54
75
  /** One consolidated summary per slot, delivered to every notifying target's endpoint. */
55
76
  sendSlotSummary(slot, schedule, rows) {
56
- const targets = this.config.delivery?.targets ?? {};
57
- const notifiable = new Set(Object.keys(targets).filter((n) => {
58
- const target = targets[n];
59
- return target?.type === 'httpMultipart' && Boolean(target.notificationUrl?.trim());
60
- }));
77
+ const notifiable = this.notifiableTargets();
61
78
  if (notifiable.size === 0 || rows.length === 0)
62
79
  return;
63
80
  const icon = (s) => s === 'submitted' ? '✅' : s === 'no_candidate' ? '⚠️' : s === 'duplicate' ? '♱' : s === 'delivery_pending' ? '🕓' : '❌';
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "type": "commonjs",
3
3
  "name": "pixivflow",
4
- "version": "2.19.0",
4
+ "version": "2.19.2",
5
5
  "private": true
6
6
  }
@@ -81,6 +81,12 @@ export declare class OutboxRepository extends BaseRepository {
81
81
  */
82
82
  claimDue(owner: string, leaseMs: number, limit: number, now?: number): OutboxRow[];
83
83
  markDone(id: string, now?: number): void;
84
+ /**
85
+ * Dead-letter a row whose failure cannot be fixed by retrying — a local
86
+ * configuration error is re-read identically on every attempt, so scheduling
87
+ * retries would only keep the row in `retry_wait` until the budget runs out.
88
+ */
89
+ markDead(id: string, error: string, now?: number): void;
84
90
  /** Schedule a later retry, or flip to dead once attempts are exhausted. */
85
91
  markRetry(id: string, nextAt: number, error: string, now?: number): OutboxStatus;
86
92
  /** Release a processing row back to pending without counting a retry. */
@@ -103,6 +103,20 @@ class OutboxRepository extends BaseRepository_1.BaseRepository {
103
103
  WHERE id=@id`)
104
104
  .run({ id, now });
105
105
  }
106
+ /**
107
+ * Dead-letter a row whose failure cannot be fixed by retrying — a local
108
+ * configuration error is re-read identically on every attempt, so scheduling
109
+ * retries would only keep the row in `retry_wait` until the budget runs out.
110
+ */
111
+ markDead(id, error, now = Date.now()) {
112
+ this.db
113
+ .prepare(`UPDATE outbox
114
+ SET attempts=attempts+1, status='dead',
115
+ lease_owner=NULL, lease_until=NULL,
116
+ last_error=@error, updated_at=@now
117
+ WHERE id=@id`)
118
+ .run({ id, error: error.slice(0, 1000), now });
119
+ }
106
120
  /** Schedule a later retry, or flip to dead once attempts are exhausted. */
107
121
  markRetry(id, nextAt, error, now = Date.now()) {
108
122
  const row = this.get(id);
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.19.0', commit: '4f4645d49dec' };
5
+ exports.BUILD = { version: '2.19.2', commit: '4b6938041a10' };
6
6
  //# sourceMappingURL=version.js.map
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "type": "commonjs",
3
3
  "name": "pixivflow-webui-backend",
4
- "version": "2.19.0",
4
+ "version": "2.19.2",
5
5
  "description": "PixivFlow WebUI Backend - CommonJS module"
6
6
  }
@@ -59,6 +59,15 @@ export declare class Transport {
59
59
  private maybeTransientRetry;
60
60
  private linearBackoffMs;
61
61
  private waitRetry;
62
+ /**
63
+ * Effective per-attempt signal = the caller's/run cancellation **OR** the
64
+ * per-request timeout, whichever fires first.
65
+ *
66
+ * Both sources must stay armed. A caller signal may not replace the timeout:
67
+ * that would let a single hung socket wait for the whole schedule timeout
68
+ * (the caller only cancels at run level). The timeout may not replace the
69
+ * caller signal either: a cancelled run must not keep its request alive.
70
+ */
62
71
  private withTimeout;
63
72
  private safeText;
64
73
  }
@@ -1 +1 @@
1
- {"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../src/transport/transport.ts"],"names":[],"mappings":"AAIA,OAAO,EAAiB,KAAK,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAaxE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,KAAK,EACV,SAAS,EACT,gBAAgB,EAChB,YAAY,EACZ,cAAc,EAEf,MAAM,UAAU,CAAC;AAElB,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,IAAI,EAAE,mBAAmB,CAAC;IAC1B,IAAI,EAAE,aAAa,CAAC;IACpB,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,IAAI,CAAC,EAAE,gBAAgB,CAAC;IACxB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7D;AAwBD;;;;GAIG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAe;IACtC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAsB;IAC3C,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAgB;IACrC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAY;IACpC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAmB;IACzC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAY;IACtC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAU;IACnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAsD;IAE9E,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAa;IAC7C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAgB;IAC/C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAyC;gBAEtD,GAAG,EAAE,eAAe;IAiDhC,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;IASrC,qEAAqE;IAC/D,OAAO,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,CAAC,CAAC;IAK7E,mDAAmD;IAC7C,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,MAAM,CAAC;IAInF,gFAAgF;IAC1E,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,WAAW,CAAC;IA0BxF,OAAO,CAAC,IAAI;IAaZ,OAAO,CAAC,WAAW;YAKL,gBAAgB;YAuChB,WAAW;YA6BX,aAAa;IAwB3B,sEAAsE;YACxD,UAAU;IAwCxB,OAAO,CAAC,cAAc;IAKtB,OAAO,CAAC,WAAW;YAoBL,eAAe;YA6Cf,eAAe;IAiD7B,OAAO,CAAC,mBAAmB;IAW3B,OAAO,CAAC,eAAe;YAIT,SAAS;IAWvB,OAAO,CAAC,WAAW;YAaL,QAAQ;CAOvB"}
1
+ {"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../src/transport/transport.ts"],"names":[],"mappings":"AAIA,OAAO,EAAiB,KAAK,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAaxE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,KAAK,EACV,SAAS,EACT,gBAAgB,EAChB,YAAY,EACZ,cAAc,EAEf,MAAM,UAAU,CAAC;AAElB,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,IAAI,EAAE,mBAAmB,CAAC;IAC1B,IAAI,EAAE,aAAa,CAAC;IACpB,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,IAAI,CAAC,EAAE,gBAAgB,CAAC;IACxB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7D;AAyCD;;;;GAIG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAe;IACtC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAsB;IAC3C,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAgB;IACrC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAY;IACpC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAmB;IACzC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAY;IACtC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAU;IACnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAsD;IAE9E,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAa;IAC7C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAgB;IAC/C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAyC;gBAEtD,GAAG,EAAE,eAAe;IAiDhC,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;IASrC,qEAAqE;IAC/D,OAAO,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,CAAC,CAAC;IAK7E,mDAAmD;IAC7C,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,MAAM,CAAC;IAInF,gFAAgF;IAC1E,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,WAAW,CAAC;IA0BxF,OAAO,CAAC,IAAI;IAaZ,OAAO,CAAC,WAAW;YAKL,gBAAgB;YAuChB,WAAW;YA6BX,aAAa;IAwB3B,sEAAsE;YACxD,UAAU;IAwCxB,OAAO,CAAC,cAAc;IAKtB,OAAO,CAAC,WAAW;YAoBL,eAAe;YA6Cf,eAAe;IA+D7B,OAAO,CAAC,mBAAmB;IAW3B,OAAO,CAAC,eAAe;YAIT,SAAS;IAgBvB;;;;;;;;OAQG;IACH,OAAO,CAAC,WAAW;YA+BL,QAAQ;CAOvB"}
@@ -14,6 +14,20 @@ const APP_HEADERS = {
14
14
  'App-OS-Version': '14.6',
15
15
  'App-Version': '7.13.3',
16
16
  };
17
+ /**
18
+ * Marker reason for the per-request timeout abort. `withTimeout()` aborts its
19
+ * own controller with it so the retry path can tell our own timeout apart from
20
+ * a caller/run cancellation: the caller reason is opaque (the downloader passes
21
+ * a plain string) and must not be inspected.
22
+ */
23
+ const TIMEOUT_REASON = '__pixiv_timeout__';
24
+ /** Structural AbortError test: also matches DOMException (not an Error subclass). */
25
+ function isAbortErrorLike(e) {
26
+ return typeof e === 'object' && e !== null && e.name === 'AbortError';
27
+ }
28
+ function isTimeoutReason(e) {
29
+ return e instanceof Error && e.message === TIMEOUT_REASON;
30
+ }
17
31
  function proxyUrl(p) {
18
32
  const protocol = (p.protocol ?? 'http').toLowerCase();
19
33
  const auth = p.username && p.password
@@ -341,17 +355,26 @@ class Transport {
341
355
  if (e instanceof errors_1.PixivAbortError) {
342
356
  return { action: 'throw', error: e };
343
357
  }
344
- // AbortError from fetch/axios: distinguish our own timeout abort from a
345
- // caller-provided signal abort. The internal timeout controller has NO
346
- // external signal, so callerAborted cleanly separates the two cases
347
- // (undici/axios attach different reasons; do not rely on their internals).
348
- if (e instanceof Error && e.name === 'AbortError') {
349
- const reason = e.cause;
350
- const isOurTimeout = !callerAborted ||
351
- (reason instanceof Error && reason.message === '__pixiv_timeout__');
352
- if (isOurTimeout) {
353
- return this.maybeTransientRetry(new errors_1.PixivTimeoutError(`Request timeout after ${this.timeoutMs}ms`, { endpoint: url, cause: e, code: 'timeout' }), attempt, url);
354
- }
358
+ // Tell our own per-request timeout apart from a caller/run cancellation.
359
+ // The abort reason is authoritative, not the error shape:
360
+ // - our timeout aborts with TIMEOUT_REASON; undici rejects the fetch with
361
+ // that reason object directly (so it arrives as a plain Error, NOT an
362
+ // AbortError), while abort-wrapping runtimes expose it via `cause`;
363
+ // - the caller reason is opaque (a plain string from the downloader), so
364
+ // it must be classified from the signal state.
365
+ const abortCause = e?.cause;
366
+ if (isTimeoutReason(e) || isTimeoutReason(abortCause)) {
367
+ return this.maybeTransientRetry(new errors_1.PixivTimeoutError(`Request timeout after ${this.timeoutMs}ms`, { endpoint: url, cause: e, code: 'timeout' }), attempt, url);
368
+ }
369
+ if (isAbortErrorLike(e) && !callerAborted) {
370
+ // An abort we cannot attribute to the caller can only be our own timeout
371
+ // (the only other abort source on this path).
372
+ return this.maybeTransientRetry(new errors_1.PixivTimeoutError(`Request timeout after ${this.timeoutMs}ms`, { endpoint: url, cause: e, code: 'timeout' }), attempt, url);
373
+ }
374
+ if (callerAborted) {
375
+ // Run/scheduler cancellation is terminal by definition and must never be
376
+ // charged to the retry budget (waitRetry would otherwise sit out the
377
+ // back-off before the next attempt noticed the cancel).
355
378
  return { action: 'throw', error: new errors_1.PixivAbortError('Request aborted', { cause: e, endpoint: url }) };
356
379
  }
357
380
  if (e instanceof errors_1.PixivTimeoutError) {
@@ -373,6 +396,11 @@ class Transport {
373
396
  return Math.min(1000 * (attempt + 1), 5000);
374
397
  }
375
398
  async waitRetry(waitMs, signal) {
399
+ // An already-aborted signal never fires 'abort' again, so the sleeper would
400
+ // sit out the entire back-off before the next attempt noticed the cancel.
401
+ if (signal?.aborted) {
402
+ throw new errors_1.PixivAbortError('aborted before retry back-off');
403
+ }
376
404
  if (waitMs <= 0)
377
405
  return;
378
406
  try {
@@ -383,17 +411,41 @@ class Transport {
383
411
  }
384
412
  }
385
413
  // -- helpers ---------------------------------------------------------------
414
+ /**
415
+ * Effective per-attempt signal = the caller's/run cancellation **OR** the
416
+ * per-request timeout, whichever fires first.
417
+ *
418
+ * Both sources must stay armed. A caller signal may not replace the timeout:
419
+ * that would let a single hung socket wait for the whole schedule timeout
420
+ * (the caller only cancels at run level). The timeout may not replace the
421
+ * caller signal either: a cancelled run must not keep its request alive.
422
+ */
386
423
  withTimeout(timeoutMs, external) {
387
- if (external)
388
- return { signal: external, cancel: () => { } };
389
424
  const controller = new AbortController();
390
- const timer = setTimeout(() => controller.abort(new Error('__pixiv_timeout__')), timeoutMs);
425
+ const timer = setTimeout(() => controller.abort(new Error(TIMEOUT_REASON)), timeoutMs);
391
426
  if (typeof timer.unref === 'function')
392
427
  timer.unref();
428
+ if (!external) {
429
+ return {
430
+ signal: controller.signal,
431
+ cancel: () => {
432
+ clearTimeout(timer);
433
+ },
434
+ };
435
+ }
436
+ // Forward the caller reason verbatim so cancellation stays observable.
437
+ const onExternalAbort = () => controller.abort(external.reason);
438
+ if (external.aborted) {
439
+ onExternalAbort();
440
+ }
441
+ else {
442
+ external.addEventListener('abort', onExternalAbort, { once: true });
443
+ }
393
444
  return {
394
445
  signal: controller.signal,
395
446
  cancel: () => {
396
447
  clearTimeout(timer);
448
+ external.removeEventListener('abort', onExternalAbort);
397
449
  },
398
450
  };
399
451
  }
@@ -1 +1 @@
1
- {"version":3,"file":"transport.js","sourceRoot":"","sources":["../../src/transport/transport.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"transport.js","sourceRoot":"","sources":["../../src/transport/transport.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,257 @@
1
+ /**
2
+ * Per-request timeout *composition* with a caller/run AbortSignal.
3
+ *
4
+ * Contract: the signal handed to `fetch` must abort when EITHER
5
+ * - the caller's run signal aborts (scheduler cancellation), OR
6
+ * - the per-request timeout elapses,
7
+ * whichever fires first. A caller signal must never *disable* the timeout.
8
+ *
9
+ * `TargetSearchRunner` threads the scheduler run signal into the kit search
10
+ * calls on the documented assumption that "the transport already combines a
11
+ * signal with its per-request timeout". These tests pin that assumption down
12
+ * with zero network access: the fake fetch below never settles on its own.
13
+ *
14
+ * Fidelity note (Node 24 / undici, verified empirically):
15
+ * - `controller.abort(reason)` makes fetch reject with `reason` itself;
16
+ * - `controller.abort()` makes fetch reject with a DOMException AbortError.
17
+ * The fake fetch mirrors both shapes so the transport classifies what it
18
+ * actually sees in production.
19
+ */
20
+ import { PixivClient } from '../../client';
21
+ import { StaticTokenProvider } from '../../auth/types';
22
+ import type { FetchLike } from '../../types';
23
+ import { PixivAbortError, PixivNetworkError, PixivTimeoutError } from '../../errors/errors';
24
+
25
+ const PER_REQUEST_TIMEOUT_MS = 80;
26
+ /** Generous relative to PER_REQUEST_TIMEOUT_MS, tiny relative to jest's 15s. */
27
+ const SETTLE_BUDGET_MS = 1_200;
28
+
29
+ type SettleOutcome = { settled: true; error?: unknown } | { settled: false };
30
+
31
+ /** Resolves as soon as `p` settles; reports `settled: false` on the deadline. */
32
+ function settleWithin(p: Promise<unknown>, ms: number): Promise<SettleOutcome> {
33
+ return new Promise<SettleOutcome>((resolve) => {
34
+ const timer = setTimeout(() => resolve({ settled: false }), ms);
35
+ p.then(
36
+ () => {
37
+ clearTimeout(timer);
38
+ resolve({ settled: true });
39
+ },
40
+ (error) => {
41
+ clearTimeout(timer);
42
+ resolve({ settled: true, error });
43
+ }
44
+ );
45
+ });
46
+ }
47
+
48
+ /**
49
+ * A fetch that hangs until its signal aborts, then rejects exactly the way
50
+ * undici rejects (with the signal reason, or a DOMException named AbortError).
51
+ * It never applies a timeout of its own: the transport must supply one.
52
+ */
53
+ function hangingFetch(counter: { calls: number }): FetchLike {
54
+ return async (_url, init) => {
55
+ counter.calls++;
56
+ const signal = init.signal ?? undefined;
57
+ await new Promise<never>((_resolve, reject) => {
58
+ const rejectLikeUndici = (): void => {
59
+ const reason: unknown = signal?.reason;
60
+ if (reason !== undefined && reason !== null) {
61
+ reject(reason);
62
+ return;
63
+ }
64
+ const e = new Error('This operation was aborted');
65
+ e.name = 'AbortError';
66
+ reject(e);
67
+ };
68
+ if (signal?.aborted) {
69
+ rejectLikeUndici();
70
+ return;
71
+ }
72
+ signal?.addEventListener('abort', rejectLikeUndici, { once: true });
73
+ });
74
+ throw new Error('unreachable');
75
+ };
76
+ }
77
+
78
+ function makeClient(fetchImpl: FetchLike, retries = 0): PixivClient {
79
+ return new PixivClient({
80
+ auth: new StaticTokenProvider('test-token'),
81
+ fetchImpl,
82
+ retries,
83
+ timeoutMs: PER_REQUEST_TIMEOUT_MS,
84
+ rateLimit: {
85
+ minIntervalMs: 0,
86
+ jitterRatio: 0,
87
+ initialCooldownMs: 60_000,
88
+ maxCooldownMs: 900_000,
89
+ openThreshold: 10,
90
+ decaySuccesses: 99,
91
+ random: () => 0,
92
+ },
93
+ });
94
+ }
95
+
96
+ function errorOf(outcome: SettleOutcome): unknown {
97
+ return outcome.settled ? outcome.error : undefined;
98
+ }
99
+
100
+ describe('per-request timeout survives a caller/run signal', () => {
101
+ it('a hung search request still times out while a run signal is attached', async () => {
102
+ const counter = { calls: 0 };
103
+ const client = makeClient(hangingFetch(counter));
104
+ const run = new AbortController(); // attached, NOT aborted
105
+
106
+ const call = client.illustrations.searchPage({ word: 'test', limit: 1, signal: run.signal }, null);
107
+ const outcome = await settleWithin(call, SETTLE_BUDGET_MS);
108
+
109
+ // Regression: with a caller signal the per-request timeout used to be
110
+ // skipped entirely, so this promise stayed pending until the whole
111
+ // schedule timed out.
112
+ expect(outcome.settled).toBe(true);
113
+ expect(errorOf(outcome)).toBeInstanceOf(PixivTimeoutError);
114
+ });
115
+
116
+ it('a hung media fetch still times out while a run signal is attached', async () => {
117
+ const counter = { calls: 0 };
118
+ const client = makeClient(hangingFetch(counter));
119
+
120
+ const call = client.media.fetch('https://i.pximg.net/img-original/img/x.jpg', {
121
+ signal: new AbortController().signal,
122
+ });
123
+ const outcome = await settleWithin(call, SETTLE_BUDGET_MS);
124
+
125
+ expect(outcome.settled).toBe(true);
126
+ expect(errorOf(outcome)).toBeInstanceOf(PixivTimeoutError);
127
+ });
128
+
129
+ it('aborting the run signal still cancels the request, with no timeout masking it', async () => {
130
+ const counter = { calls: 0 };
131
+ const client = makeClient(hangingFetch(counter));
132
+ const run = new AbortController();
133
+
134
+ const call = client.illustrations.searchPage({ word: 'test', limit: 1, signal: run.signal }, null);
135
+ setTimeout(() => run.abort(), 10);
136
+
137
+ const outcome = await settleWithin(call, SETTLE_BUDGET_MS);
138
+ expect(outcome.settled).toBe(true);
139
+ expect(errorOf(outcome)).toBeInstanceOf(PixivAbortError);
140
+ expect(counter.calls).toBe(1);
141
+ });
142
+
143
+ it('cancels promptly when the run signal aborts during retry back-off', async () => {
144
+ let calls = 0;
145
+ const client = makeClient(
146
+ async () => {
147
+ calls++;
148
+ throw Object.assign(new Error('read ECONNRESET'), { code: 'ECONNRESET' });
149
+ },
150
+ 3
151
+ );
152
+
153
+ const run = new AbortController();
154
+ const call = client.illustrations.searchPage({ word: 'test', limit: 1, signal: run.signal }, null);
155
+ setTimeout(() => run.abort(), 30);
156
+
157
+ const outcome = await settleWithin(call, SETTLE_BUDGET_MS);
158
+ expect(outcome.settled).toBe(true);
159
+ expect(errorOf(outcome)).toBeInstanceOf(PixivAbortError);
160
+ // The back-off must not be waited out and the retry budget must not be burned.
161
+ expect(calls).toBe(1);
162
+ });
163
+
164
+ it('keeps retrying transient network failures while the run signal stays active', async () => {
165
+ let calls = 0;
166
+ const client = makeClient(async () => {
167
+ calls++;
168
+ throw Object.assign(new Error('read ECONNRESET'), { code: 'ECONNRESET' });
169
+ }, 2);
170
+
171
+ const run = new AbortController();
172
+ const call = client.illustrations.searchPage({ word: 'test', limit: 1, signal: run.signal }, null);
173
+ const outcome = await settleWithin(call, 4_000);
174
+
175
+ expect(outcome.settled).toBe(true);
176
+ expect(errorOf(outcome)).toBeInstanceOf(PixivNetworkError);
177
+ expect(calls).toBe(3); // retries honoured: an attached signal is not a cancellation
178
+ });
179
+
180
+ it('removes its abort listener from the caller signal once the request settles', async () => {
181
+ const counter = { calls: 0 };
182
+ const client = makeClient(hangingFetch(counter));
183
+ const run = new AbortController();
184
+ const added = jest.spyOn(run.signal, 'addEventListener');
185
+ const removed = jest.spyOn(run.signal, 'removeEventListener');
186
+
187
+ const call = client.illustrations.searchPage({ word: 'test', limit: 1, signal: run.signal }, null);
188
+ const outcome = await settleWithin(call, SETTLE_BUDGET_MS);
189
+ expect(outcome.settled).toBe(true);
190
+
191
+ expect(added).toHaveBeenCalled();
192
+ // No listener leak: every abort listener added is taken off again.
193
+ expect(removed.mock.calls.length).toBe(added.mock.calls.length);
194
+
195
+ // Already settled: aborting afterwards must not reject anything a second time.
196
+ expect(() => run.abort()).not.toThrow();
197
+ });
198
+
199
+ it('without a caller signal the per-request timeout is unchanged', async () => {
200
+ const counter = { calls: 0 };
201
+ const client = makeClient(hangingFetch(counter));
202
+
203
+ const call = client.illustrations.searchPage({ word: 'test', limit: 1 });
204
+ const outcome = await settleWithin(call, SETTLE_BUDGET_MS);
205
+
206
+ expect(outcome.settled).toBe(true);
207
+ expect(errorOf(outcome)).toBeInstanceOf(PixivTimeoutError);
208
+ });
209
+
210
+ it('clears the per-request timer once the request settles', async () => {
211
+ jest.useFakeTimers();
212
+ try {
213
+ const counter = { calls: 0 };
214
+ const client = makeClient(hangingFetch(counter));
215
+ const baseline = jest.getTimerCount();
216
+
217
+ const call = client.illustrations.searchPage({ word: 'test', limit: 1 });
218
+ void call.catch(() => undefined); // observed below via rejects
219
+ expect(jest.getTimerCount()).toBeGreaterThan(baseline); // timeout armed
220
+
221
+ await jest.advanceTimersByTimeAsync(PER_REQUEST_TIMEOUT_MS);
222
+
223
+ await expect(call).rejects.toBeInstanceOf(PixivTimeoutError);
224
+ // No leaked timer: `cancel()` in the finally block cleared it.
225
+ expect(jest.getTimerCount()).toBe(baseline);
226
+ } finally {
227
+ jest.useRealTimers();
228
+ }
229
+ });
230
+
231
+ it('settles once and rejects nothing else when a run signal aborts first', async () => {
232
+ const counter = { calls: 0 };
233
+ const client = makeClient(hangingFetch(counter));
234
+ const run = new AbortController();
235
+ const unhandled: unknown[] = [];
236
+ const onUnhandled = (reason: unknown): void => {
237
+ unhandled.push(reason);
238
+ };
239
+ process.on('unhandledRejection', onUnhandled);
240
+ try {
241
+ // A plain string reason, exactly as DownloadManager.cancel() passes it.
242
+ const call = client.illustrations.searchPage({ word: 'test', limit: 1, signal: run.signal }, null);
243
+ run.abort('run cancelled');
244
+
245
+ const outcome = await settleWithin(call, SETTLE_BUDGET_MS);
246
+ expect(outcome.settled).toBe(true);
247
+ expect(errorOf(outcome)).toBeInstanceOf(PixivAbortError);
248
+
249
+ // Outlive the per-request deadline: the cleared timer must not abort (or
250
+ // reject) anything a second time.
251
+ await new Promise((resolve) => setTimeout(resolve, PER_REQUEST_TIMEOUT_MS * 2));
252
+ expect(unhandled).toEqual([]);
253
+ } finally {
254
+ process.off('unhandledRejection', onUnhandled);
255
+ }
256
+ });
257
+ });
@@ -46,6 +46,23 @@ const APP_HEADERS = {
46
46
  'App-Version': '7.13.3',
47
47
  };
48
48
 
49
+ /**
50
+ * Marker reason for the per-request timeout abort. `withTimeout()` aborts its
51
+ * own controller with it so the retry path can tell our own timeout apart from
52
+ * a caller/run cancellation: the caller reason is opaque (the downloader passes
53
+ * a plain string) and must not be inspected.
54
+ */
55
+ const TIMEOUT_REASON = '__pixiv_timeout__';
56
+
57
+ /** Structural AbortError test: also matches DOMException (not an Error subclass). */
58
+ function isAbortErrorLike(e: unknown): boolean {
59
+ return typeof e === 'object' && e !== null && (e as { name?: unknown }).name === 'AbortError';
60
+ }
61
+
62
+ function isTimeoutReason(e: unknown): boolean {
63
+ return e instanceof Error && e.message === TIMEOUT_REASON;
64
+ }
65
+
49
66
 
50
67
  function proxyUrl(p: ProxyOptions): string {
51
68
  const protocol = (p.protocol ?? 'http').toLowerCase();
@@ -419,22 +436,36 @@ export class Transport {
419
436
  return { action: 'throw', error: e };
420
437
  }
421
438
 
422
- // AbortError from fetch/axios: distinguish our own timeout abort from a
423
- // caller-provided signal abort. The internal timeout controller has NO
424
- // external signal, so callerAborted cleanly separates the two cases
425
- // (undici/axios attach different reasons; do not rely on their internals).
426
- if (e instanceof Error && e.name === 'AbortError') {
427
- const reason = (e as { cause?: unknown }).cause;
428
- const isOurTimeout =
429
- !callerAborted ||
430
- (reason instanceof Error && reason.message === '__pixiv_timeout__');
431
- if (isOurTimeout) {
432
- return this.maybeTransientRetry(
433
- new PixivTimeoutError(`Request timeout after ${this.timeoutMs}ms`, { endpoint: url, cause: e, code: 'timeout' }),
434
- attempt,
435
- url
436
- );
437
- }
439
+ // Tell our own per-request timeout apart from a caller/run cancellation.
440
+ // The abort reason is authoritative, not the error shape:
441
+ // - our timeout aborts with TIMEOUT_REASON; undici rejects the fetch with
442
+ // that reason object directly (so it arrives as a plain Error, NOT an
443
+ // AbortError), while abort-wrapping runtimes expose it via `cause`;
444
+ // - the caller reason is opaque (a plain string from the downloader), so
445
+ // it must be classified from the signal state.
446
+ const abortCause = (e as { cause?: unknown } | null)?.cause;
447
+ if (isTimeoutReason(e) || isTimeoutReason(abortCause)) {
448
+ return this.maybeTransientRetry(
449
+ new PixivTimeoutError(`Request timeout after ${this.timeoutMs}ms`, { endpoint: url, cause: e, code: 'timeout' }),
450
+ attempt,
451
+ url
452
+ );
453
+ }
454
+
455
+ if (isAbortErrorLike(e) && !callerAborted) {
456
+ // An abort we cannot attribute to the caller can only be our own timeout
457
+ // (the only other abort source on this path).
458
+ return this.maybeTransientRetry(
459
+ new PixivTimeoutError(`Request timeout after ${this.timeoutMs}ms`, { endpoint: url, cause: e, code: 'timeout' }),
460
+ attempt,
461
+ url
462
+ );
463
+ }
464
+
465
+ if (callerAborted) {
466
+ // Run/scheduler cancellation is terminal by definition and must never be
467
+ // charged to the retry budget (waitRetry would otherwise sit out the
468
+ // back-off before the next attempt noticed the cancel).
438
469
  return { action: 'throw', error: new PixivAbortError('Request aborted', { cause: e, endpoint: url }) };
439
470
  }
440
471
 
@@ -467,6 +498,11 @@ export class Transport {
467
498
  }
468
499
 
469
500
  private async waitRetry(waitMs: number, signal?: AbortSignal): Promise<void> {
501
+ // An already-aborted signal never fires 'abort' again, so the sleeper would
502
+ // sit out the entire back-off before the next attempt noticed the cancel.
503
+ if (signal?.aborted) {
504
+ throw new PixivAbortError('aborted before retry back-off');
505
+ }
470
506
  if (waitMs <= 0) return;
471
507
  try {
472
508
  await this.sleeper(waitMs, signal);
@@ -477,15 +513,42 @@ export class Transport {
477
513
 
478
514
  // -- helpers ---------------------------------------------------------------
479
515
 
516
+ /**
517
+ * Effective per-attempt signal = the caller's/run cancellation **OR** the
518
+ * per-request timeout, whichever fires first.
519
+ *
520
+ * Both sources must stay armed. A caller signal may not replace the timeout:
521
+ * that would let a single hung socket wait for the whole schedule timeout
522
+ * (the caller only cancels at run level). The timeout may not replace the
523
+ * caller signal either: a cancelled run must not keep its request alive.
524
+ */
480
525
  private withTimeout(timeoutMs: number, external?: AbortSignal): { signal: AbortSignal; cancel: () => void } {
481
- if (external) return { signal: external, cancel: () => {} };
482
526
  const controller = new AbortController();
483
- const timer = setTimeout(() => controller.abort(new Error('__pixiv_timeout__')), timeoutMs);
527
+ const timer = setTimeout(() => controller.abort(new Error(TIMEOUT_REASON)), timeoutMs);
484
528
  if (typeof timer.unref === 'function') timer.unref();
529
+
530
+ if (!external) {
531
+ return {
532
+ signal: controller.signal,
533
+ cancel: () => {
534
+ clearTimeout(timer);
535
+ },
536
+ };
537
+ }
538
+
539
+ // Forward the caller reason verbatim so cancellation stays observable.
540
+ const onExternalAbort = (): void => controller.abort(external.reason);
541
+ if (external.aborted) {
542
+ onExternalAbort();
543
+ } else {
544
+ external.addEventListener('abort', onExternalAbort, { once: true });
545
+ }
546
+
485
547
  return {
486
548
  signal: controller.signal,
487
549
  cancel: () => {
488
550
  clearTimeout(timer);
551
+ external.removeEventListener('abort', onExternalAbort);
489
552
  },
490
553
  };
491
554
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pixivflow",
3
- "version": "2.19.0",
3
+ "version": "2.19.2",
4
4
  "description": "🎨 智能的 Pixiv 自动化下载工具 - 支持批量下载插画和小说、定时任务、Docker部署 | Intelligent Pixiv Automation Downloader with batch download, scheduler, and Docker support",
5
5
  "repository": {
6
6
  "type": "git",