pixivflow 2.16.1 → 2.17.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/dist/auth/PixivAuth.d.ts +12 -0
- package/dist/auth/PixivAuth.d.ts.map +1 -1
- package/dist/auth/PixivAuth.js +26 -0
- package/dist/auth/PixivAuth.js.map +1 -1
- package/dist/batch/executionResult.d.ts +85 -0
- package/dist/batch/executionResult.d.ts.map +1 -0
- package/dist/batch/executionResult.js +102 -0
- package/dist/batch/executionResult.js.map +1 -0
- package/dist/batch/runDiagnostics.d.ts +48 -0
- package/dist/batch/runDiagnostics.d.ts.map +1 -0
- package/dist/batch/runDiagnostics.js +103 -0
- package/dist/batch/runDiagnostics.js.map +1 -0
- package/dist/commands/Command.d.ts +5 -0
- package/dist/commands/Command.d.ts.map +1 -1
- package/dist/commands/Command.js +7 -0
- package/dist/commands/Command.js.map +1 -1
- package/dist/commands/ExecuteSlotCommand.d.ts +37 -0
- package/dist/commands/ExecuteSlotCommand.d.ts.map +1 -0
- package/dist/commands/ExecuteSlotCommand.js +267 -0
- package/dist/commands/ExecuteSlotCommand.js.map +1 -0
- package/dist/commands/index.d.ts +2 -1
- package/dist/commands/index.d.ts.map +1 -1
- package/dist/commands/index.js +4 -1
- package/dist/commands/index.js.map +1 -1
- package/dist/commands/scheduler-runtime.d.ts +37 -1
- package/dist/commands/scheduler-runtime.d.ts.map +1 -1
- package/dist/commands/scheduler-runtime.js +52 -19
- package/dist/commands/scheduler-runtime.js.map +1 -1
- package/dist/commands/types.d.ts +6 -0
- package/dist/commands/types.d.ts.map +1 -1
- package/dist/config/types.d.ts +33 -1
- package/dist/config/types.d.ts.map +1 -1
- package/dist/config/validation.d.ts +14 -1
- package/dist/config/validation.d.ts.map +1 -1
- package/dist/config/validation.js +109 -33
- package/dist/config/validation.js.map +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js.map +1 -1
- package/dist/delivery/DeliveryDispatcher.d.ts.map +1 -1
- package/dist/delivery/DeliveryDispatcher.js +7 -0
- package/dist/delivery/DeliveryDispatcher.js.map +1 -1
- package/dist/delivery/HttpMultipartDelivery.d.ts +12 -0
- package/dist/delivery/HttpMultipartDelivery.d.ts.map +1 -1
- package/dist/delivery/HttpMultipartDelivery.js +89 -70
- package/dist/delivery/HttpMultipartDelivery.js.map +1 -1
- package/dist/delivery/TelegramReviewDelivery.d.ts +49 -0
- package/dist/delivery/TelegramReviewDelivery.d.ts.map +1 -0
- package/dist/delivery/TelegramReviewDelivery.js +307 -0
- package/dist/delivery/TelegramReviewDelivery.js.map +1 -0
- package/dist/download/DownloadManager.d.ts +10 -0
- package/dist/download/DownloadManager.d.ts.map +1 -1
- package/dist/download/DownloadManager.js +21 -0
- package/dist/download/DownloadManager.js.map +1 -1
- package/dist/download/plan/DownloadPlanner.d.ts +10 -0
- package/dist/download/plan/DownloadPlanner.d.ts.map +1 -1
- package/dist/download/plan/DownloadPlanner.js +19 -0
- package/dist/download/plan/DownloadPlanner.js.map +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/notification/NotificationPolicy.d.ts.map +1 -1
- package/dist/notification/NotificationPolicy.js +4 -1
- package/dist/notification/NotificationPolicy.js.map +1 -1
- package/dist/package.json +1 -1
- package/dist/pixiv-token-getter-adapter.d.ts +27 -7
- package/dist/pixiv-token-getter-adapter.d.ts.map +1 -1
- package/dist/pixiv-token-getter-adapter.js +44 -27
- package/dist/pixiv-token-getter-adapter.js.map +1 -1
- package/dist/utils/concurrency.d.ts.map +1 -1
- package/dist/utils/concurrency.js +9 -2
- package/dist/utils/concurrency.js.map +1 -1
- package/dist/utils/config-validator-unified.d.ts.map +1 -1
- package/dist/utils/config-validator-unified.js +15 -1
- package/dist/utils/config-validator-unified.js.map +1 -1
- package/dist/utils/token-maintenance.d.ts +0 -4
- package/dist/utils/token-maintenance.d.ts.map +1 -1
- package/dist/utils/token-maintenance.js +5 -25
- package/dist/utils/token-maintenance.js.map +1 -1
- package/dist/version.js +1 -1
- package/dist/webui/package.json +1 -1
- package/package.json +2 -2
package/dist/auth/PixivAuth.d.ts
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
import { NetworkConfig, PixivCredentialConfig } from '../config';
|
|
2
2
|
import { Database } from '../storage/Database';
|
|
3
|
+
/**
|
|
4
|
+
* Read-only auth: never exchange a refresh token, never persist one.
|
|
5
|
+
*
|
|
6
|
+
* Two processes can share one refresh token, but Pixiv's rotation behaviour on
|
|
7
|
+
* `grant_type=refresh_token` is a server detail a client cannot prove. If it
|
|
8
|
+
* rotates, a second process that refreshes can invalidate the first one's token —
|
|
9
|
+
* and a long-running daemon never re-reads the token from disk, so it cannot
|
|
10
|
+
* recover without a restart. In this mode the only accepted credential is an
|
|
11
|
+
* access token already present in the local cache; anything else fails loudly
|
|
12
|
+
* instead of silently rotating a credential someone else is using.
|
|
13
|
+
*/
|
|
14
|
+
export declare function isAuthReadOnly(): boolean;
|
|
3
15
|
export declare class PixivAuth {
|
|
4
16
|
private readonly credentials;
|
|
5
17
|
private readonly network;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PixivAuth.d.ts","sourceRoot":"","sources":["../../src/auth/PixivAuth.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAEjE,OAAO,EAAoB,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAmBjE,qBAAa,SAAS;IAIlB,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAL3B,OAAO,CAAC,UAAU,CAAC,CAAS;gBAGT,WAAW,EAAE,qBAAqB,EAClC,OAAO,EAAE,aAAa,EACtB,QAAQ,EAAE,QAAQ,EACnC,UAAU,CAAC,EAAE,MAAM;IAKR,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"PixivAuth.d.ts","sourceRoot":"","sources":["../../src/auth/PixivAuth.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAEjE,OAAO,EAAoB,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAmBjE;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,IAAI,OAAO,CAGxC;AAED,qBAAa,SAAS;IAIlB,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAL3B,OAAO,CAAC,UAAU,CAAC,CAAS;gBAGT,WAAW,EAAE,qBAAqB,EAClC,OAAO,EAAE,aAAa,EACtB,QAAQ,EAAE,QAAQ,EACnC,UAAU,CAAC,EAAE,MAAM;IAKR,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC;IAiB9C;;;OAGG;IACG,2BAA2B,IAAI,OAAO,CAAC,MAAM,CAAC;YAKtC,kBAAkB;IAoJhC,OAAO,CAAC,kBAAkB;CAI3B"}
|
package/dist/auth/PixivAuth.js
CHANGED
|
@@ -34,6 +34,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.PixivAuth = void 0;
|
|
37
|
+
exports.isAuthReadOnly = isAuthReadOnly;
|
|
37
38
|
const node_crypto_1 = require("node:crypto");
|
|
38
39
|
const promises_1 = require("node:timers/promises");
|
|
39
40
|
const logger_1 = require("../logger");
|
|
@@ -41,6 +42,21 @@ const login_helper_1 = require("../utils/login-helper");
|
|
|
41
42
|
const errors_1 = require("../utils/errors");
|
|
42
43
|
const TOKEN_CACHE_KEY = 'pixiv_access_token';
|
|
43
44
|
const REFRESH_TOKEN_CACHE_KEY = 'pixiv_refresh_token';
|
|
45
|
+
/**
|
|
46
|
+
* Read-only auth: never exchange a refresh token, never persist one.
|
|
47
|
+
*
|
|
48
|
+
* Two processes can share one refresh token, but Pixiv's rotation behaviour on
|
|
49
|
+
* `grant_type=refresh_token` is a server detail a client cannot prove. If it
|
|
50
|
+
* rotates, a second process that refreshes can invalidate the first one's token —
|
|
51
|
+
* and a long-running daemon never re-reads the token from disk, so it cannot
|
|
52
|
+
* recover without a restart. In this mode the only accepted credential is an
|
|
53
|
+
* access token already present in the local cache; anything else fails loudly
|
|
54
|
+
* instead of silently rotating a credential someone else is using.
|
|
55
|
+
*/
|
|
56
|
+
function isAuthReadOnly() {
|
|
57
|
+
const value = process.env.PIXIV_AUTH_READONLY?.trim().toLowerCase();
|
|
58
|
+
return value === '1' || value === 'true' || value === 'yes';
|
|
59
|
+
}
|
|
44
60
|
class PixivAuth {
|
|
45
61
|
credentials;
|
|
46
62
|
network;
|
|
@@ -57,6 +73,10 @@ class PixivAuth {
|
|
|
57
73
|
if (cached && cached.accessToken && cached.expiresAt > Date.now() + 60_000) {
|
|
58
74
|
return cached.accessToken;
|
|
59
75
|
}
|
|
76
|
+
if (isAuthReadOnly()) {
|
|
77
|
+
throw new errors_1.AuthenticationError('Read-only auth (PIXIV_AUTH_READONLY) refuses to refresh: no usable access token is cached. ' +
|
|
78
|
+
'Seed the access-token cache with a token that is still valid, or run with its own credential.');
|
|
79
|
+
}
|
|
60
80
|
const refreshed = await this.refreshAccessToken();
|
|
61
81
|
return refreshed.accessToken;
|
|
62
82
|
}
|
|
@@ -69,6 +89,12 @@ class PixivAuth {
|
|
|
69
89
|
return stored.accessToken;
|
|
70
90
|
}
|
|
71
91
|
async refreshAccessToken() {
|
|
92
|
+
// Single guard for every refresh caller: the persistence block below writes a
|
|
93
|
+
// rotated token to the database, a file and the config, in this process only.
|
|
94
|
+
if (isAuthReadOnly()) {
|
|
95
|
+
throw new errors_1.AuthenticationError('Read-only auth (PIXIV_AUTH_READONLY) must never call the token endpoint: ' +
|
|
96
|
+
'refreshing may rotate a refresh token another process is using.');
|
|
97
|
+
}
|
|
72
98
|
const url = 'https://oauth.secure.pixiv.net/auth/token';
|
|
73
99
|
let lastError;
|
|
74
100
|
for (let attempt = 0; attempt < (this.network.retries ?? 3); attempt++) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PixivAuth.js","sourceRoot":"","sources":["../../src/auth/PixivAuth.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"PixivAuth.js","sourceRoot":"","sources":["../../src/auth/PixivAuth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Machine-readable result of one batch execution.
|
|
3
|
+
*
|
|
4
|
+
* The batch runner is a disposable CI job: it cannot leave its state behind in a
|
|
5
|
+
* process, so its *only* handoff is this document. Everything a control plane
|
|
6
|
+
* needs to roll the occurrence up — and everything a human needs to debug a
|
|
7
|
+
* night's failure — has to be in here.
|
|
8
|
+
*
|
|
9
|
+
* Two rules the shape enforces:
|
|
10
|
+
* - a target that produced NO outcome is reported as `missing`, never omitted and
|
|
11
|
+
* never assumed successful;
|
|
12
|
+
* - the exit code IS the execution status (0 success / 2 partial / 3 failed /
|
|
13
|
+
* 4 uncertain), so a supervisor that only reads the exit code still cannot
|
|
14
|
+
* mistake "some targets failed" for "everything worked".
|
|
15
|
+
*/
|
|
16
|
+
import type { TargetOutcome } from '../scheduler/TargetOutcome';
|
|
17
|
+
export type BatchTargetStatus = 'submitted' | 'stored' | 'delivery_pending' | 'no_candidate' | 'duplicate' | 'failed'
|
|
18
|
+
/** The run produced no outcome for this target at all (aborted mid-way). */
|
|
19
|
+
| 'missing';
|
|
20
|
+
export type BatchExecutionStatus = 'success' | 'partial' | 'failed' | 'uncertain';
|
|
21
|
+
export interface BatchTargetResult {
|
|
22
|
+
targetId: string;
|
|
23
|
+
status: BatchTargetStatus;
|
|
24
|
+
workId?: string;
|
|
25
|
+
error?: string;
|
|
26
|
+
/** Only meaningful for `failed`: a later attempt may still succeed. */
|
|
27
|
+
retryable?: boolean;
|
|
28
|
+
}
|
|
29
|
+
export interface BatchOutboxSummary {
|
|
30
|
+
processed: number;
|
|
31
|
+
done: number;
|
|
32
|
+
retried: number;
|
|
33
|
+
dead: number;
|
|
34
|
+
}
|
|
35
|
+
export interface BatchExecutionResult {
|
|
36
|
+
slotId: string;
|
|
37
|
+
scheduleId: string;
|
|
38
|
+
botId?: string;
|
|
39
|
+
attempt: number;
|
|
40
|
+
mode: 'live' | 'shadow' | 'dry-run';
|
|
41
|
+
occurrenceAt?: number;
|
|
42
|
+
status: BatchExecutionStatus;
|
|
43
|
+
exitCode: number;
|
|
44
|
+
startedAt: string;
|
|
45
|
+
finishedAt: string;
|
|
46
|
+
durationMs: number;
|
|
47
|
+
targets: BatchTargetResult[];
|
|
48
|
+
outbox?: BatchOutboxSummary;
|
|
49
|
+
/** Process-level failure (config, auth, crash): not a per-target outcome. */
|
|
50
|
+
error?: string;
|
|
51
|
+
/**
|
|
52
|
+
* The category that best explains a failed run, and the server's own cooldown
|
|
53
|
+
* hint when it gave one.
|
|
54
|
+
*
|
|
55
|
+
* The control plane needs these to choose a retry delay: a rate-limited account
|
|
56
|
+
* should wait for the server, while a broken provider should not be retried on the
|
|
57
|
+
* same schedule. Exit codes alone cannot express that difference.
|
|
58
|
+
*/
|
|
59
|
+
errorClass?: string;
|
|
60
|
+
retryAfterMs?: number | null;
|
|
61
|
+
/** How many Pixiv 429s this run observed; 0 or absent means none. */
|
|
62
|
+
rateLimitHits?: number;
|
|
63
|
+
}
|
|
64
|
+
export declare const EXIT_SUCCESS = 0;
|
|
65
|
+
export declare const EXIT_ERROR = 1;
|
|
66
|
+
export declare const EXIT_PARTIAL = 2;
|
|
67
|
+
export declare const EXIT_FAILED = 3;
|
|
68
|
+
export declare const EXIT_UNCERTAIN = 4;
|
|
69
|
+
export declare function outcomeToTargetResult(targetId: string, outcome: TargetOutcome): BatchTargetResult;
|
|
70
|
+
export interface ExecutionSummary {
|
|
71
|
+
status: BatchExecutionStatus;
|
|
72
|
+
exitCode: number;
|
|
73
|
+
targets: BatchTargetResult[];
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Combine per-target results into the execution's status.
|
|
77
|
+
*
|
|
78
|
+
* `expectedTargetIds` is what makes this honest: a target that never reported is
|
|
79
|
+
* added as `missing` instead of being dropped, so a run that died halfway cannot
|
|
80
|
+
* come out as `success`.
|
|
81
|
+
*/
|
|
82
|
+
export declare function summarizeExecution(results: readonly BatchTargetResult[], expectedTargetIds: readonly string[]): ExecutionSummary;
|
|
83
|
+
/** Exit code → execution status, the contract the control plane relies on. */
|
|
84
|
+
export declare function executionStatusForExitCode(exitCode: number): BatchExecutionStatus;
|
|
85
|
+
//# sourceMappingURL=executionResult.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"executionResult.d.ts","sourceRoot":"","sources":["../../src/batch/executionResult.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAEhE,MAAM,MAAM,iBAAiB,GACzB,WAAW,GACX,QAAQ,GACR,kBAAkB,GAClB,cAAc,GACd,WAAW,GACX,QAAQ;AACV,4EAA4E;GAC1E,SAAS,CAAC;AAEd,MAAM,MAAM,oBAAoB,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,WAAW,CAAC;AAElF,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,iBAAiB,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uEAAuE;IACvE,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,CAAC;IACpC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,oBAAoB,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,iBAAiB,EAAE,CAAC;IAC7B,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAC5B,6EAA6E;IAC7E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,qEAAqE;IACrE,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,eAAO,MAAM,YAAY,IAAI,CAAC;AAC9B,eAAO,MAAM,UAAU,IAAI,CAAC;AAC5B,eAAO,MAAM,YAAY,IAAI,CAAC;AAC9B,eAAO,MAAM,WAAW,IAAI,CAAC;AAC7B,eAAO,MAAM,cAAc,IAAI,CAAC;AAKhC,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,iBAAiB,CAoBjG;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,oBAAoB,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,iBAAiB,EAAE,CAAC;CAC9B;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,SAAS,iBAAiB,EAAE,EACrC,iBAAiB,EAAE,SAAS,MAAM,EAAE,GACnC,gBAAgB,CAmClB;AAED,8EAA8E;AAC9E,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,MAAM,GAAG,oBAAoB,CAWjF"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Machine-readable result of one batch execution.
|
|
4
|
+
*
|
|
5
|
+
* The batch runner is a disposable CI job: it cannot leave its state behind in a
|
|
6
|
+
* process, so its *only* handoff is this document. Everything a control plane
|
|
7
|
+
* needs to roll the occurrence up — and everything a human needs to debug a
|
|
8
|
+
* night's failure — has to be in here.
|
|
9
|
+
*
|
|
10
|
+
* Two rules the shape enforces:
|
|
11
|
+
* - a target that produced NO outcome is reported as `missing`, never omitted and
|
|
12
|
+
* never assumed successful;
|
|
13
|
+
* - the exit code IS the execution status (0 success / 2 partial / 3 failed /
|
|
14
|
+
* 4 uncertain), so a supervisor that only reads the exit code still cannot
|
|
15
|
+
* mistake "some targets failed" for "everything worked".
|
|
16
|
+
*/
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.EXIT_UNCERTAIN = exports.EXIT_FAILED = exports.EXIT_PARTIAL = exports.EXIT_ERROR = exports.EXIT_SUCCESS = void 0;
|
|
19
|
+
exports.outcomeToTargetResult = outcomeToTargetResult;
|
|
20
|
+
exports.summarizeExecution = summarizeExecution;
|
|
21
|
+
exports.executionStatusForExitCode = executionStatusForExitCode;
|
|
22
|
+
exports.EXIT_SUCCESS = 0;
|
|
23
|
+
exports.EXIT_ERROR = 1;
|
|
24
|
+
exports.EXIT_PARTIAL = 2;
|
|
25
|
+
exports.EXIT_FAILED = 3;
|
|
26
|
+
exports.EXIT_UNCERTAIN = 4;
|
|
27
|
+
/** Outcomes that mean "this target is done and content went somewhere". */
|
|
28
|
+
const OK_STATUSES = ['submitted', 'stored', 'duplicate'];
|
|
29
|
+
function outcomeToTargetResult(targetId, outcome) {
|
|
30
|
+
switch (outcome.kind) {
|
|
31
|
+
case 'submitted':
|
|
32
|
+
return { targetId, status: 'submitted', workId: outcome.workId };
|
|
33
|
+
case 'stored':
|
|
34
|
+
return { targetId, status: 'stored', workId: outcome.workId };
|
|
35
|
+
case 'delivery_pending':
|
|
36
|
+
return { targetId, status: 'delivery_pending', workId: outcome.workId };
|
|
37
|
+
case 'duplicate':
|
|
38
|
+
return { targetId, status: 'duplicate', workId: outcome.workId, error: outcome.reason };
|
|
39
|
+
case 'no_candidate':
|
|
40
|
+
return { targetId, status: 'no_candidate', error: outcome.reason };
|
|
41
|
+
case 'failed':
|
|
42
|
+
return {
|
|
43
|
+
targetId,
|
|
44
|
+
status: 'failed',
|
|
45
|
+
error: outcome.error,
|
|
46
|
+
retryable: outcome.retryable,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Combine per-target results into the execution's status.
|
|
52
|
+
*
|
|
53
|
+
* `expectedTargetIds` is what makes this honest: a target that never reported is
|
|
54
|
+
* added as `missing` instead of being dropped, so a run that died halfway cannot
|
|
55
|
+
* come out as `success`.
|
|
56
|
+
*/
|
|
57
|
+
function summarizeExecution(results, expectedTargetIds) {
|
|
58
|
+
const byTarget = new Map(results.map((result) => [result.targetId, result]));
|
|
59
|
+
const targets = expectedTargetIds.map((targetId) => byTarget.get(targetId) ?? {
|
|
60
|
+
targetId,
|
|
61
|
+
status: 'missing',
|
|
62
|
+
error: 'no outcome was produced for this target',
|
|
63
|
+
});
|
|
64
|
+
for (const result of results) {
|
|
65
|
+
if (!expectedTargetIds.includes(result.targetId))
|
|
66
|
+
targets.push(result);
|
|
67
|
+
}
|
|
68
|
+
const ok = targets.filter((target) => OK_STATUSES.includes(target.status));
|
|
69
|
+
const uncertain = targets.filter((target) => target.status === 'delivery_pending');
|
|
70
|
+
if (uncertain.length > 0) {
|
|
71
|
+
// An unconfirmed Telegram send must never be retried automatically: the
|
|
72
|
+
// control plane treats this as terminal and a human resolves it.
|
|
73
|
+
return { status: 'uncertain', exitCode: exports.EXIT_UNCERTAIN, targets };
|
|
74
|
+
}
|
|
75
|
+
if (targets.length === 0) {
|
|
76
|
+
return { status: 'failed', exitCode: exports.EXIT_FAILED, targets };
|
|
77
|
+
}
|
|
78
|
+
if (ok.length === targets.length) {
|
|
79
|
+
return { status: 'success', exitCode: exports.EXIT_SUCCESS, targets };
|
|
80
|
+
}
|
|
81
|
+
if (ok.length === 0) {
|
|
82
|
+
// Nothing was delivered. All-empty-candidates is a business outcome (retrying
|
|
83
|
+
// the same day rarely helps) but it is still "nothing published", not success.
|
|
84
|
+
const allNoCandidate = targets.every((target) => target.status === 'no_candidate');
|
|
85
|
+
return { status: allNoCandidate ? 'partial' : 'failed', exitCode: allNoCandidate ? exports.EXIT_PARTIAL : exports.EXIT_FAILED, targets };
|
|
86
|
+
}
|
|
87
|
+
return { status: 'partial', exitCode: exports.EXIT_PARTIAL, targets };
|
|
88
|
+
}
|
|
89
|
+
/** Exit code → execution status, the contract the control plane relies on. */
|
|
90
|
+
function executionStatusForExitCode(exitCode) {
|
|
91
|
+
switch (exitCode) {
|
|
92
|
+
case exports.EXIT_SUCCESS:
|
|
93
|
+
return 'success';
|
|
94
|
+
case exports.EXIT_PARTIAL:
|
|
95
|
+
return 'partial';
|
|
96
|
+
case exports.EXIT_UNCERTAIN:
|
|
97
|
+
return 'uncertain';
|
|
98
|
+
default:
|
|
99
|
+
return 'failed';
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=executionResult.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"executionResult.js","sourceRoot":"","sources":["../../src/batch/executionResult.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Run-scoped diagnostics for the business errors a batch execution hits.
|
|
3
|
+
*
|
|
4
|
+
* The control plane needs to tell a rate-limited run apart from a broken one: they
|
|
5
|
+
* share an exit code but not a remedy. A batch runner has no daemon behind it, so
|
|
6
|
+
* the only way that distinction survives is if this process records it and the
|
|
7
|
+
* result file carries it back.
|
|
8
|
+
*
|
|
9
|
+
* Deliberately module-level and reset per run: the runner is a fresh process each
|
|
10
|
+
* time, and a long-lived caller (tests, the scheduler) must not inherit counts.
|
|
11
|
+
*/
|
|
12
|
+
/** Stable categories the control plane understands. */
|
|
13
|
+
export type RunErrorCategory = 'pixiv_rate_limit' | 'network_timeout' | 'download_failed' | 'provider_error' | 'internal_error';
|
|
14
|
+
export interface RunDiagnostics {
|
|
15
|
+
categories: Partial<Record<RunErrorCategory, number>>;
|
|
16
|
+
/** How many times a Pixiv 429 was observed. */
|
|
17
|
+
rateLimitHits: number;
|
|
18
|
+
/** The longest cooldown the server asked for, if it said. */
|
|
19
|
+
maxRetryAfterMs: number | null;
|
|
20
|
+
/** The category that best explains a failed run, if any. */
|
|
21
|
+
dominantCategory: RunErrorCategory | null;
|
|
22
|
+
}
|
|
23
|
+
/** Called at the start of a run so counts cannot leak between runs. */
|
|
24
|
+
export declare function resetRunDiagnostics(): void;
|
|
25
|
+
/**
|
|
26
|
+
* Record one observed Pixiv rate limit.
|
|
27
|
+
*
|
|
28
|
+
* `waitMs` is the server's own hint when it provided one (Retry-After); the longest
|
|
29
|
+
* hint seen during the run is what the report carries, because it is the one that
|
|
30
|
+
* governs when this account may be used again.
|
|
31
|
+
*/
|
|
32
|
+
export declare function recordRateLimit(waitMs?: number): void;
|
|
33
|
+
/**
|
|
34
|
+
* Classify a failure message into a category.
|
|
35
|
+
*
|
|
36
|
+
* Message matching is the fallback, not the primary mechanism: the Pixiv client
|
|
37
|
+
* raises typed errors and the paths that see them call `recordRateLimit` directly.
|
|
38
|
+
* This exists for the places where only a string survives, and it is intentionally
|
|
39
|
+
* narrower than a generic "is this retryable" test — the point is to keep a rate
|
|
40
|
+
* limit from being confused with a broken provider.
|
|
41
|
+
*/
|
|
42
|
+
export declare function classifyRunError(message: string): RunErrorCategory;
|
|
43
|
+
/** Record a failure the run actually hit, from its message. */
|
|
44
|
+
export declare function recordRunError(message: string): RunErrorCategory;
|
|
45
|
+
/** Record an explicit category (used where the caller already knows it). */
|
|
46
|
+
export declare function recordRunCategory(category: RunErrorCategory): void;
|
|
47
|
+
export declare function runDiagnostics(): RunDiagnostics;
|
|
48
|
+
//# sourceMappingURL=runDiagnostics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runDiagnostics.d.ts","sourceRoot":"","sources":["../../src/batch/runDiagnostics.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,uDAAuD;AACvD,MAAM,MAAM,gBAAgB,GACxB,kBAAkB,GAClB,iBAAiB,GACjB,iBAAiB,GACjB,gBAAgB,GAChB,gBAAgB,CAAC;AAErB,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,OAAO,CAAC,MAAM,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC,CAAC;IACtD,+CAA+C;IAC/C,aAAa,EAAE,MAAM,CAAC;IACtB,6DAA6D;IAC7D,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,4DAA4D;IAC5D,gBAAgB,EAAE,gBAAgB,GAAG,IAAI,CAAC;CAC3C;AAWD,uEAAuE;AACvE,wBAAgB,mBAAmB,IAAI,IAAI,CAE1C;AAMD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAMrD;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,gBAAgB,CAOlE;AAED,+DAA+D;AAC/D,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,gBAAgB,CAShE;AAED,4EAA4E;AAC5E,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,gBAAgB,GAAG,IAAI,CAKlE;AAED,wBAAgB,cAAc,IAAI,cAAc,CAiB/C"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Run-scoped diagnostics for the business errors a batch execution hits.
|
|
4
|
+
*
|
|
5
|
+
* The control plane needs to tell a rate-limited run apart from a broken one: they
|
|
6
|
+
* share an exit code but not a remedy. A batch runner has no daemon behind it, so
|
|
7
|
+
* the only way that distinction survives is if this process records it and the
|
|
8
|
+
* result file carries it back.
|
|
9
|
+
*
|
|
10
|
+
* Deliberately module-level and reset per run: the runner is a fresh process each
|
|
11
|
+
* time, and a long-lived caller (tests, the scheduler) must not inherit counts.
|
|
12
|
+
*/
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.resetRunDiagnostics = resetRunDiagnostics;
|
|
15
|
+
exports.recordRateLimit = recordRateLimit;
|
|
16
|
+
exports.classifyRunError = classifyRunError;
|
|
17
|
+
exports.recordRunError = recordRunError;
|
|
18
|
+
exports.recordRunCategory = recordRunCategory;
|
|
19
|
+
exports.runDiagnostics = runDiagnostics;
|
|
20
|
+
const empty = () => ({
|
|
21
|
+
categories: {},
|
|
22
|
+
rateLimitHits: 0,
|
|
23
|
+
maxRetryAfterMs: null,
|
|
24
|
+
dominantCategory: null,
|
|
25
|
+
});
|
|
26
|
+
let state = empty();
|
|
27
|
+
/** Called at the start of a run so counts cannot leak between runs. */
|
|
28
|
+
function resetRunDiagnostics() {
|
|
29
|
+
state = empty();
|
|
30
|
+
}
|
|
31
|
+
function record(category) {
|
|
32
|
+
state.categories[category] = (state.categories[category] ?? 0) + 1;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Record one observed Pixiv rate limit.
|
|
36
|
+
*
|
|
37
|
+
* `waitMs` is the server's own hint when it provided one (Retry-After); the longest
|
|
38
|
+
* hint seen during the run is what the report carries, because it is the one that
|
|
39
|
+
* governs when this account may be used again.
|
|
40
|
+
*/
|
|
41
|
+
function recordRateLimit(waitMs) {
|
|
42
|
+
state.rateLimitHits += 1;
|
|
43
|
+
if (typeof waitMs === 'number' && Number.isFinite(waitMs) && waitMs > 0) {
|
|
44
|
+
state.maxRetryAfterMs = Math.max(state.maxRetryAfterMs ?? 0, waitMs);
|
|
45
|
+
}
|
|
46
|
+
record('pixiv_rate_limit');
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Classify a failure message into a category.
|
|
50
|
+
*
|
|
51
|
+
* Message matching is the fallback, not the primary mechanism: the Pixiv client
|
|
52
|
+
* raises typed errors and the paths that see them call `recordRateLimit` directly.
|
|
53
|
+
* This exists for the places where only a string survives, and it is intentionally
|
|
54
|
+
* narrower than a generic "is this retryable" test — the point is to keep a rate
|
|
55
|
+
* limit from being confused with a broken provider.
|
|
56
|
+
*/
|
|
57
|
+
function classifyRunError(message) {
|
|
58
|
+
if (/\b429\b|rate.?limit|too many requests|cooldown/i.test(message))
|
|
59
|
+
return 'pixiv_rate_limit';
|
|
60
|
+
if (/timeout|timed out|abort|econnreset|econnrefused|enotfound|socket hang up/i.test(message)) {
|
|
61
|
+
return 'network_timeout';
|
|
62
|
+
}
|
|
63
|
+
if (/download|file|write|disk|enospc/i.test(message))
|
|
64
|
+
return 'download_failed';
|
|
65
|
+
return 'internal_error';
|
|
66
|
+
}
|
|
67
|
+
/** Record a failure the run actually hit, from its message. */
|
|
68
|
+
function recordRunError(message) {
|
|
69
|
+
const category = classifyRunError(message);
|
|
70
|
+
if (category === 'pixiv_rate_limit') {
|
|
71
|
+
state.rateLimitHits += 1;
|
|
72
|
+
record(category);
|
|
73
|
+
return category;
|
|
74
|
+
}
|
|
75
|
+
record(category);
|
|
76
|
+
return category;
|
|
77
|
+
}
|
|
78
|
+
/** Record an explicit category (used where the caller already knows it). */
|
|
79
|
+
function recordRunCategory(category) {
|
|
80
|
+
if (category === 'pixiv_rate_limit') {
|
|
81
|
+
state.rateLimitHits += 1;
|
|
82
|
+
}
|
|
83
|
+
record(category);
|
|
84
|
+
}
|
|
85
|
+
function runDiagnostics() {
|
|
86
|
+
const rank = [
|
|
87
|
+
'pixiv_rate_limit',
|
|
88
|
+
'network_timeout',
|
|
89
|
+
'download_failed',
|
|
90
|
+
'provider_error',
|
|
91
|
+
'internal_error',
|
|
92
|
+
];
|
|
93
|
+
// A rate limit outranks everything: it is the one category with a server-provided
|
|
94
|
+
// remedy, and reporting it as "internal_error" would hide that.
|
|
95
|
+
const dominant = rank.find((category) => (state.categories[category] ?? 0) > 0) ?? null;
|
|
96
|
+
return {
|
|
97
|
+
categories: { ...state.categories },
|
|
98
|
+
rateLimitHits: state.rateLimitHits,
|
|
99
|
+
maxRetryAfterMs: state.maxRetryAfterMs,
|
|
100
|
+
dominantCategory: dominant,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=runDiagnostics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runDiagnostics.js","sourceRoot":"","sources":["../../src/batch/runDiagnostics.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;;AA8BH,kDAEC;AAaD,0CAMC;AAWD,4CAOC;AAGD,wCASC;AAGD,8CAKC;AAED,wCAiBC;AAxFD,MAAM,KAAK,GAAG,GAAmB,EAAE,CAAC,CAAC;IACnC,UAAU,EAAE,EAAE;IACd,aAAa,EAAE,CAAC;IAChB,eAAe,EAAE,IAAI;IACrB,gBAAgB,EAAE,IAAI;CACvB,CAAC,CAAC;AAEH,IAAI,KAAK,GAAG,KAAK,EAAE,CAAC;AAEpB,uEAAuE;AACvE,SAAgB,mBAAmB;IACjC,KAAK,GAAG,KAAK,EAAE,CAAC;AAClB,CAAC;AAED,SAAS,MAAM,CAAC,QAA0B;IACxC,KAAK,CAAC,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;AACrE,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,eAAe,CAAC,MAAe;IAC7C,KAAK,CAAC,aAAa,IAAI,CAAC,CAAC;IACzB,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;QACxE,KAAK,CAAC,eAAe,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,eAAe,IAAI,CAAC,EAAE,MAAM,CAAC,CAAC;IACvE,CAAC;IACD,MAAM,CAAC,kBAAkB,CAAC,CAAC;AAC7B,CAAC;AAED;;;;;;;;GAQG;AACH,SAAgB,gBAAgB,CAAC,OAAe;IAC9C,IAAI,iDAAiD,CAAC,IAAI,CAAC,OAAO,CAAC;QAAE,OAAO,kBAAkB,CAAC;IAC/F,IAAI,2EAA2E,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QAC9F,OAAO,iBAAiB,CAAC;IAC3B,CAAC;IACD,IAAI,kCAAkC,CAAC,IAAI,CAAC,OAAO,CAAC;QAAE,OAAO,iBAAiB,CAAC;IAC/E,OAAO,gBAAgB,CAAC;AAC1B,CAAC;AAED,+DAA+D;AAC/D,SAAgB,cAAc,CAAC,OAAe;IAC5C,MAAM,QAAQ,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;IAC3C,IAAI,QAAQ,KAAK,kBAAkB,EAAE,CAAC;QACpC,KAAK,CAAC,aAAa,IAAI,CAAC,CAAC;QACzB,MAAM,CAAC,QAAQ,CAAC,CAAC;QACjB,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,MAAM,CAAC,QAAQ,CAAC,CAAC;IACjB,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,4EAA4E;AAC5E,SAAgB,iBAAiB,CAAC,QAA0B;IAC1D,IAAI,QAAQ,KAAK,kBAAkB,EAAE,CAAC;QACpC,KAAK,CAAC,aAAa,IAAI,CAAC,CAAC;IAC3B,CAAC;IACD,MAAM,CAAC,QAAQ,CAAC,CAAC;AACnB,CAAC;AAED,SAAgB,cAAc;IAC5B,MAAM,IAAI,GAAuB;QAC/B,kBAAkB;QAClB,iBAAiB;QACjB,iBAAiB;QACjB,gBAAgB;QAChB,gBAAgB;KACjB,CAAC;IACF,kFAAkF;IAClF,gEAAgE;IAChE,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC;IACxF,OAAO;QACL,UAAU,EAAE,EAAE,GAAG,KAAK,CAAC,UAAU,EAAE;QACnC,aAAa,EAAE,KAAK,CAAC,aAAa;QAClC,eAAe,EAAE,KAAK,CAAC,eAAe;QACtC,gBAAgB,EAAE,QAAQ;KAC3B,CAAC;AACJ,CAAC"}
|
|
@@ -67,6 +67,11 @@ export declare abstract class BaseCommand implements Command {
|
|
|
67
67
|
* Create a failure result
|
|
68
68
|
*/
|
|
69
69
|
protected failure(error: Error | string, data?: unknown): CommandResult;
|
|
70
|
+
/**
|
|
71
|
+
* Attach an explicit process exit code (batch/CI commands: a partial run and a
|
|
72
|
+
* failed run are different outcomes for a supervisor).
|
|
73
|
+
*/
|
|
74
|
+
protected withExitCode(result: CommandResult, exitCode: number): CommandResult;
|
|
70
75
|
/**
|
|
71
76
|
* Check if command name or alias matches
|
|
72
77
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Command.d.ts","sourceRoot":"","sources":["../../src/commands/Command.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AACvF,OAAO,EAAE,eAAe,EAAoB,MAAM,YAAY,CAAC;AAE/D;;GAEG;AACH,MAAM,WAAW,OAAO;IACtB;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB;;OAEG;IACH,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAE7B;;;OAGG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;IAEjC;;OAEG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IAE5B;;OAEG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,eAAe,CAAC;IAEpC;;;;;OAKG;IACH,OAAO,CAAC,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IAE5E;;;;OAIG;IACH,QAAQ,CAAC,CAAC,IAAI,EAAE,WAAW,GAAG,gBAAgB,CAAC;IAE/C;;;OAGG;IACH,QAAQ,CAAC,IAAI,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,8BAAsB,WAAY,YAAW,OAAO;IAClD,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IACtC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAQ;IACvC,QAAQ,CAAC,QAAQ,CAAC,EAAE,eAAe,CAAC;IAEpC,QAAQ,CAAC,OAAO,CAAC,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,aAAa,CAAC;IAEpF,QAAQ,CAAC,CAAC,IAAI,EAAE,WAAW,GAAG,gBAAgB;IAI9C,QAAQ,CAAC,IAAI,MAAM;IAInB;;OAEG;IACH,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,aAAa;IAIlE;;OAEG;IACH,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,aAAa;IAKvE;;OAEG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAU9B;;OAEG;IACH,WAAW,IAAI,eAAe;CAG/B"}
|
|
1
|
+
{"version":3,"file":"Command.d.ts","sourceRoot":"","sources":["../../src/commands/Command.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AACvF,OAAO,EAAE,eAAe,EAAoB,MAAM,YAAY,CAAC;AAE/D;;GAEG;AACH,MAAM,WAAW,OAAO;IACtB;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB;;OAEG;IACH,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAE7B;;;OAGG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;IAEjC;;OAEG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IAE5B;;OAEG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,eAAe,CAAC;IAEpC;;;;;OAKG;IACH,OAAO,CAAC,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IAE5E;;;;OAIG;IACH,QAAQ,CAAC,CAAC,IAAI,EAAE,WAAW,GAAG,gBAAgB,CAAC;IAE/C;;;OAGG;IACH,QAAQ,CAAC,IAAI,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,8BAAsB,WAAY,YAAW,OAAO;IAClD,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IACtC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAQ;IACvC,QAAQ,CAAC,QAAQ,CAAC,EAAE,eAAe,CAAC;IAEpC,QAAQ,CAAC,OAAO,CAAC,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,aAAa,CAAC;IAEpF,QAAQ,CAAC,CAAC,IAAI,EAAE,WAAW,GAAG,gBAAgB;IAI9C,QAAQ,CAAC,IAAI,MAAM;IAInB;;OAEG;IACH,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,aAAa;IAIlE;;OAEG;IACH,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,aAAa;IAKvE;;;OAGG;IACH,SAAS,CAAC,YAAY,CAAC,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,GAAG,aAAa;IAI9E;;OAEG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAU9B;;OAEG;IACH,WAAW,IAAI,eAAe;CAG/B"}
|
package/dist/commands/Command.js
CHANGED
|
@@ -31,6 +31,13 @@ class BaseCommand {
|
|
|
31
31
|
const errorObj = error instanceof Error ? error : new Error(error);
|
|
32
32
|
return { success: false, error: errorObj, data };
|
|
33
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* Attach an explicit process exit code (batch/CI commands: a partial run and a
|
|
36
|
+
* failed run are different outcomes for a supervisor).
|
|
37
|
+
*/
|
|
38
|
+
withExitCode(result, exitCode) {
|
|
39
|
+
return { ...result, exitCode };
|
|
40
|
+
}
|
|
34
41
|
/**
|
|
35
42
|
* Check if command name or alias matches
|
|
36
43
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Command.js","sourceRoot":"","sources":["../../src/commands/Command.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAGH,yCAA+D;AAsD/D;;GAEG;AACH,MAAsB,WAAW;IAGtB,OAAO,CAAY;IACnB,aAAa,GAAY,IAAI,CAAC;IAC9B,QAAQ,CAAmB;IAIpC,QAAQ,CAAE,IAAiB;QACzB,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IACrC,CAAC;IAED,QAAQ;QACN,OAAO,GAAG,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,WAAW,EAAE,CAAC;IAC7C,CAAC;IAED;;OAEG;IACO,OAAO,CAAC,OAAgB,EAAE,IAAc;QAChD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC1C,CAAC;IAED;;OAEG;IACO,OAAO,CAAC,KAAqB,EAAE,IAAc;QACrD,MAAM,QAAQ,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC;QACnE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IACnD,CAAC;IAED;;OAEG;IACH,OAAO,CAAC,IAAY;QAClB,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;YACvB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACrC,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;OAEG;IACH,WAAW;QACT,OAAO,IAAI,CAAC,QAAQ,IAAI,2BAAgB,CAAC;IAC3C,CAAC;CACF;
|
|
1
|
+
{"version":3,"file":"Command.js","sourceRoot":"","sources":["../../src/commands/Command.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAGH,yCAA+D;AAsD/D;;GAEG;AACH,MAAsB,WAAW;IAGtB,OAAO,CAAY;IACnB,aAAa,GAAY,IAAI,CAAC;IAC9B,QAAQ,CAAmB;IAIpC,QAAQ,CAAE,IAAiB;QACzB,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IACrC,CAAC;IAED,QAAQ;QACN,OAAO,GAAG,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,WAAW,EAAE,CAAC;IAC7C,CAAC;IAED;;OAEG;IACO,OAAO,CAAC,OAAgB,EAAE,IAAc;QAChD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC1C,CAAC;IAED;;OAEG;IACO,OAAO,CAAC,KAAqB,EAAE,IAAc;QACrD,MAAM,QAAQ,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC;QACnE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IACnD,CAAC;IAED;;;OAGG;IACO,YAAY,CAAC,MAAqB,EAAE,QAAgB;QAC5D,OAAO,EAAE,GAAG,MAAM,EAAE,QAAQ,EAAE,CAAC;IACjC,CAAC;IAED;;OAEG;IACH,OAAO,CAAC,IAAY;QAClB,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;YACvB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACrC,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;OAEG;IACH,WAAW;QACT,OAAO,IAAI,CAAC,QAAQ,IAAI,2BAAgB,CAAC;IAC3C,CAAC;CACF;AA3DD,kCA2DC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* execute-slot: run ONE canonical occurrence as a disposable batch job.
|
|
3
|
+
*
|
|
4
|
+
* This is the execution plane of the serverless production architecture. The
|
|
5
|
+
* control plane has already decided *which* occurrence is due and hands the runner
|
|
6
|
+
* its canonical identity; the runner never re-derives "what should run today" and
|
|
7
|
+
* never opens a long-lived daemon:
|
|
8
|
+
*
|
|
9
|
+
* control plane → workflow_dispatch(slot_id, schedule_id, occurrence_at, ...)
|
|
10
|
+
* → this command runs exactly that slot's targets once
|
|
11
|
+
* → writes one machine-readable result document
|
|
12
|
+
* → exits with a status-bearing code
|
|
13
|
+
*
|
|
14
|
+
* Deliberately NOT `pixivflow scheduler`: no cron, no slots, no leases, no local
|
|
15
|
+
* ledger requirement. Duplicate history still comes from the local database when
|
|
16
|
+
* one is present, and the control plane owns cross-runner duplicate state.
|
|
17
|
+
*/
|
|
18
|
+
import { BaseCommand } from './Command';
|
|
19
|
+
import { CommandCategory } from './metadata';
|
|
20
|
+
import { CommandContext, CommandArgs, CommandResult } from './types';
|
|
21
|
+
export declare class ExecuteSlotCommand extends BaseCommand {
|
|
22
|
+
readonly name = "execute-slot";
|
|
23
|
+
readonly description = "Execute one canonical occurrence once (batch/CI execution plane)";
|
|
24
|
+
readonly aliases: string[];
|
|
25
|
+
readonly metadata: {
|
|
26
|
+
category: CommandCategory;
|
|
27
|
+
requiresAuth: boolean;
|
|
28
|
+
longRunning: boolean;
|
|
29
|
+
};
|
|
30
|
+
validate(args: CommandArgs): {
|
|
31
|
+
valid: boolean;
|
|
32
|
+
errors: string[];
|
|
33
|
+
};
|
|
34
|
+
execute(context: CommandContext, args: CommandArgs): Promise<CommandResult>;
|
|
35
|
+
getUsage(): string;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=ExecuteSlotCommand.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExecuteSlotCommand.d.ts","sourceRoot":"","sources":["../../src/commands/ExecuteSlotCommand.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAIH,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAiCrE,qBAAa,kBAAmB,SAAQ,WAAW;IACjD,QAAQ,CAAC,IAAI,kBAAkB;IAC/B,QAAQ,CAAC,WAAW,sEAAsE;IAC1F,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,CAAa;IACvC,QAAQ,CAAC,QAAQ;;;;MAIf;IAEF,QAAQ,CAAC,IAAI,EAAE,WAAW;;;;IAqBpB,OAAO,CAAC,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,aAAa,CAAC;IA+IjF,QAAQ,IAAI,MAAM;CAqCnB"}
|