@iworkflow/core 0.5.0 → 0.6.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.
- package/README.md +3 -1
- package/dist/errors.d.ts +3 -0
- package/dist/heartbeat.d.ts +10 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +9 -7
- package/package.json +1 -1
- package/src/errors.ts +4 -1
- package/src/heartbeat.ts +16 -6
- package/src/index.ts +1 -1
package/README.md
CHANGED
|
@@ -17,6 +17,8 @@ export const outreach: Flow = async (ctx, input: { id: string }) => {
|
|
|
17
17
|
```
|
|
18
18
|
|
|
19
19
|
Шаг с прогрессом: `heartbeat(details)` и `lastHeartbeat()` из этого пакета внутри функции шага.
|
|
20
|
+
Рантайм шага ставит адаптер на время шага (`stepScope`): в одном процессе могут жить оба движка.
|
|
21
|
+
`@iworkflow/core` и адаптеры — одной версии: область шага общая через `Symbol.for`.
|
|
20
22
|
|
|
21
23
|
Отказы одинаковы на обоих движках. Шаг бросает `nonRetryable(message, type, details)` или
|
|
22
24
|
`new Failure(message, { type })`; порт бросает `FlowError` с `reason` (`failed`, `timeout`,
|
|
@@ -36,6 +38,6 @@ try {
|
|
|
36
38
|
|
|
37
39
|
Приоритет: `client.start(..., { priority })` (1 — первым, 5 — последним) → `ctx.priority`; шаги и
|
|
38
40
|
дети его наследуют, `StepOptions.priority` — свой. Срок повтора из отказа: `new Failure(msg, { type,
|
|
39
|
-
retryAfterMs })
|
|
41
|
+
retryAfterMs })`; `benign: true` — штатный отказ, Temporal не пишет его ошибкой. Номер попытки в шаге — `stepAttempt()`. Время в процессе — `await ctx.now()`.
|
|
40
42
|
`client.signalWithStart(target, args, opts, topic, value)` — сигнал идущему или запуск с сигналом.
|
|
41
43
|
Контракт обоих движков — `lab/test/contract.test.ts` репозитория.
|
package/dist/errors.d.ts
CHANGED
|
@@ -8,11 +8,14 @@ export declare class Failure extends Error {
|
|
|
8
8
|
readonly nonRetryable: boolean;
|
|
9
9
|
/** Следующая попытка шага не раньше чем через столько мс (FLOOD_WAIT): вместо паузы из StepOptions. */
|
|
10
10
|
readonly retryAfterMs?: number;
|
|
11
|
+
/** Штатный отказ (флуд, тихие часы): Temporal не пишет его в журнал ошибкой (category BENIGN). */
|
|
12
|
+
readonly benign: boolean;
|
|
11
13
|
constructor(message: string, opts: {
|
|
12
14
|
type: string;
|
|
13
15
|
details?: unknown;
|
|
14
16
|
nonRetryable?: boolean;
|
|
15
17
|
retryAfterMs?: number;
|
|
18
|
+
benign?: boolean;
|
|
16
19
|
});
|
|
17
20
|
}
|
|
18
21
|
/** Отказ без повтора: `throw nonRetryable("нет такой фазы", "UnknownPhase")`. */
|
package/dist/heartbeat.d.ts
CHANGED
|
@@ -4,7 +4,16 @@ export interface StepRuntime {
|
|
|
4
4
|
/** Номер попытки шага, с 1. */
|
|
5
5
|
attempt(): number;
|
|
6
6
|
}
|
|
7
|
-
|
|
7
|
+
/** Область шага: какой рантайм у шага, что идёт сейчас. Самый внутренний шаг — свой, без угадывания движка. */
|
|
8
|
+
export interface StepScope {
|
|
9
|
+
run<T>(rt: StepRuntime, fn: () => T): T;
|
|
10
|
+
current(): StepRuntime | undefined;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Одна область на процесс; её создаёт первый адаптер (AsyncLocalStorage) — core читает песочница
|
|
14
|
+
* Temporal, и node:async_hooks ему импортировать нельзя.
|
|
15
|
+
*/
|
|
16
|
+
export declare function stepScope(make: () => StepScope): StepScope;
|
|
8
17
|
/** Отметить, что шаг жив, и сохранить прогресс. */
|
|
9
18
|
export declare const heartbeat: (details?: unknown) => Promise<void>;
|
|
10
19
|
/** Прогресс прошлой попытки этого шага; undefined — первая попытка или прогресса не было. */
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export * from "./types";
|
|
2
|
-
export {
|
|
2
|
+
export { heartbeat, lastHeartbeat, stepAttempt, stepScope, type StepRuntime, type StepScope } from "./heartbeat";
|
|
3
3
|
export * from "./errors";
|
|
4
4
|
export { exitSignal, type ExitSignal } from "./exit";
|
package/dist/index.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
// src/heartbeat.ts
|
|
2
|
-
var KEY = Symbol.for("@iworkflow/core.step-
|
|
3
|
-
function
|
|
4
|
-
globalThis[KEY]
|
|
2
|
+
var KEY = Symbol.for("@iworkflow/core.step-scope");
|
|
3
|
+
function stepScope(make) {
|
|
4
|
+
return globalThis[KEY] ??= make();
|
|
5
5
|
}
|
|
6
6
|
function current() {
|
|
7
|
-
const rt = globalThis[KEY];
|
|
7
|
+
const rt = globalThis[KEY]?.current();
|
|
8
8
|
if (!rt)
|
|
9
|
-
throw new Error("heartbeat вне шага:
|
|
9
|
+
throw new Error("heartbeat вне шага: шаг движка процесса сейчас не идёт");
|
|
10
10
|
return rt;
|
|
11
11
|
}
|
|
12
12
|
var heartbeat = (details) => current().heartbeat(details);
|
|
@@ -18,12 +18,14 @@ class Failure extends Error {
|
|
|
18
18
|
details;
|
|
19
19
|
nonRetryable;
|
|
20
20
|
retryAfterMs;
|
|
21
|
+
benign;
|
|
21
22
|
constructor(message, opts) {
|
|
22
23
|
super(message);
|
|
23
24
|
this.name = "Failure";
|
|
24
25
|
this.type = opts.type;
|
|
25
26
|
this.details = opts.details;
|
|
26
27
|
this.nonRetryable = opts.nonRetryable ?? false;
|
|
28
|
+
this.benign = opts.benign ?? false;
|
|
27
29
|
const after = opts.retryAfterMs;
|
|
28
30
|
this.retryAfterMs = after !== undefined && Number.isFinite(after) && after >= 0 ? after : undefined;
|
|
29
31
|
}
|
|
@@ -81,12 +83,12 @@ export {
|
|
|
81
83
|
DEFAULT_PRIORITY,
|
|
82
84
|
Failure,
|
|
83
85
|
FlowError,
|
|
84
|
-
bindStepRuntime,
|
|
85
86
|
checkPriority,
|
|
86
87
|
exitSignal,
|
|
87
88
|
heartbeat,
|
|
88
89
|
isFlowError,
|
|
89
90
|
lastHeartbeat,
|
|
90
91
|
nonRetryable,
|
|
91
|
-
stepAttempt
|
|
92
|
+
stepAttempt,
|
|
93
|
+
stepScope
|
|
92
94
|
};
|
package/package.json
CHANGED
package/src/errors.ts
CHANGED
|
@@ -10,15 +10,18 @@ export class Failure extends Error {
|
|
|
10
10
|
readonly nonRetryable: boolean;
|
|
11
11
|
/** Следующая попытка шага не раньше чем через столько мс (FLOOD_WAIT): вместо паузы из StepOptions. */
|
|
12
12
|
readonly retryAfterMs?: number;
|
|
13
|
+
/** Штатный отказ (флуд, тихие часы): Temporal не пишет его в журнал ошибкой (category BENIGN). */
|
|
14
|
+
readonly benign: boolean;
|
|
13
15
|
constructor(
|
|
14
16
|
message: string,
|
|
15
|
-
opts: { type: string; details?: unknown; nonRetryable?: boolean; retryAfterMs?: number },
|
|
17
|
+
opts: { type: string; details?: unknown; nonRetryable?: boolean; retryAfterMs?: number; benign?: boolean },
|
|
16
18
|
) {
|
|
17
19
|
super(message);
|
|
18
20
|
this.name = "Failure";
|
|
19
21
|
this.type = opts.type;
|
|
20
22
|
this.details = opts.details;
|
|
21
23
|
this.nonRetryable = opts.nonRetryable ?? false;
|
|
24
|
+
this.benign = opts.benign ?? false;
|
|
22
25
|
// Неразобранный срок (NaN, отрицательный) — как не заданный: пауза из StepOptions.
|
|
23
26
|
const after = opts.retryAfterMs;
|
|
24
27
|
this.retryAfterMs = after !== undefined && Number.isFinite(after) && after >= 0 ? after : undefined;
|
package/src/heartbeat.ts
CHANGED
|
@@ -8,16 +8,26 @@ export interface StepRuntime {
|
|
|
8
8
|
attempt(): number;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
/** Область шага: какой рантайм у шага, что идёт сейчас. Самый внутренний шаг — свой, без угадывания движка. */
|
|
12
|
+
export interface StepScope {
|
|
13
|
+
run<T>(rt: StepRuntime, fn: () => T): T;
|
|
14
|
+
current(): StepRuntime | undefined;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const KEY = Symbol.for("@iworkflow/core.step-scope");
|
|
18
|
+
type Slot = { [KEY]?: StepScope };
|
|
13
19
|
|
|
14
|
-
|
|
15
|
-
|
|
20
|
+
/**
|
|
21
|
+
* Одна область на процесс; её создаёт первый адаптер (AsyncLocalStorage) — core читает песочница
|
|
22
|
+
* Temporal, и node:async_hooks ему импортировать нельзя.
|
|
23
|
+
*/
|
|
24
|
+
export function stepScope(make: () => StepScope): StepScope {
|
|
25
|
+
return ((globalThis as Slot)[KEY] ??= make());
|
|
16
26
|
}
|
|
17
27
|
|
|
18
28
|
function current(): StepRuntime {
|
|
19
|
-
const rt = (globalThis as Slot)[KEY];
|
|
20
|
-
if (!rt) throw new Error("heartbeat вне шага:
|
|
29
|
+
const rt = (globalThis as Slot)[KEY]?.current();
|
|
30
|
+
if (!rt) throw new Error("heartbeat вне шага: шаг движка процесса сейчас не идёт");
|
|
21
31
|
return rt;
|
|
22
32
|
}
|
|
23
33
|
|
package/src/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export * from "./types";
|
|
2
|
-
export {
|
|
2
|
+
export { heartbeat, lastHeartbeat, stepAttempt, stepScope, type StepRuntime, type StepScope } from "./heartbeat";
|
|
3
3
|
export * from "./errors";
|
|
4
4
|
export { exitSignal, type ExitSignal } from "./exit";
|