effect-inngest 0.3.0-beta.3 → 0.4.0-beta1
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 +69 -75
- package/dist/Client.js +1 -1
- package/dist/Cron.d.ts +17 -0
- package/dist/Cron.js +24 -0
- package/dist/Events.d.ts +1 -1
- package/dist/Events.js +1 -1
- package/dist/Function.d.ts +28 -26
- package/dist/Function.js +19 -11
- package/dist/Group.d.ts +7 -7
- package/dist/Group.js +1 -0
- package/dist/HttpApi.js +2 -1
- package/dist/Inngest.d.ts +60 -0
- package/dist/Inngest.js +61 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +4 -2
- package/dist/internal/checkpoint/Abort.d.ts +1 -0
- package/dist/internal/checkpoint/Abort.js +5 -0
- package/dist/internal/checkpoint/State.d.ts +1 -1
- package/dist/internal/checkpoint/State.js +8 -1
- package/dist/internal/codec/StepResult.js +2 -12
- package/dist/internal/driver.js +1 -0
- package/dist/internal/errors.js +1 -1
- package/dist/internal/execution/ExecutionResponse.js +33 -4
- package/dist/internal/execution/HandlerRun.js +2 -1
- package/dist/internal/handler.js +37 -24
- package/dist/internal/protocol.js +3 -0
- package/dist/internal/runtime/HandlerContext.d.ts +0 -2
- package/dist/internal/runtime/HandlerContext.js +0 -3
- package/dist/internal/runtime/StepTools.d.ts +8 -16
- package/dist/internal/runtime/StepTools.js +2 -8
- package/dist/internal/runtime/steps/InvokeStep.js +1 -2
- package/dist/internal/runtime/steps/StepRun.js +25 -19
- package/dist/internal/serve/HttpApp.js +2 -1
- package/dist/internal/utils/safe-stringify.js +50 -0
- package/package.json +17 -1
- package/src/Client.ts +1 -1
- package/src/Cron.ts +33 -0
- package/src/Events.ts +1 -1
- package/src/Function.ts +58 -34
- package/src/Group.ts +10 -7
- package/src/HttpApi.ts +7 -1
- package/src/Inngest.ts +85 -0
- package/src/index.ts +21 -7
- package/src/internal/checkpoint/Abort.ts +5 -0
- package/src/internal/checkpoint/State.ts +8 -0
- package/src/internal/codec/StepResult.ts +1 -43
- package/src/internal/driver.ts +13 -2
- package/src/internal/errors.ts +1 -3
- package/src/internal/execution/ExecutionResponse.ts +44 -1
- package/src/internal/execution/HandlerRun.ts +3 -2
- package/src/internal/handler.ts +39 -34
- package/src/internal/protocol.ts +3 -0
- package/src/internal/runtime/HandlerContext.ts +2 -5
- package/src/internal/runtime/StepTools.ts +4 -31
- package/src/internal/runtime/steps/InvokeStep.ts +1 -4
- package/src/internal/runtime/steps/StepRun.ts +28 -44
- package/src/internal/serve/HttpApp.ts +1 -0
- package/src/internal/utils/safe-stringify.ts +84 -0
package/dist/Group.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { InngestClient } from "./Client.js";
|
|
2
2
|
import { InngestFunction } from "./Function.js";
|
|
3
3
|
import { HandlerContext } from "./internal/runtime/HandlerContext.js";
|
|
4
|
+
import { StepTools } from "./internal/runtime/StepTools.js";
|
|
4
5
|
import { Context, Effect, Layer } from "effect";
|
|
5
6
|
import * as HttpClient from "effect/unstable/http/HttpClient";
|
|
6
7
|
import * as _$effect_unstable_http_HttpServerRequest0 from "effect/unstable/http/HttpServerRequest";
|
|
@@ -24,7 +25,7 @@ type TypeId = typeof TypeId;
|
|
|
24
25
|
* @since 0.1.0
|
|
25
26
|
* @category models
|
|
26
27
|
*/
|
|
27
|
-
type HandlerFn<F extends InngestFunction.Any> = (context: HandlerContext<F>) => Effect.Effect<
|
|
28
|
+
type HandlerFn<F extends InngestFunction.Any> = (context: HandlerContext<F>) => Effect.Effect<unknown, unknown, unknown>;
|
|
28
29
|
/**
|
|
29
30
|
* @since 0.1.0
|
|
30
31
|
* @category models
|
|
@@ -41,12 +42,13 @@ type HandlerFrom<Fns extends InngestFunction.Any, Tag extends InngestFunction.Ta
|
|
|
41
42
|
* @since 0.1.0
|
|
42
43
|
* @category models
|
|
43
44
|
*/
|
|
44
|
-
type
|
|
45
|
+
type RuntimeRequirements = InngestClient | StepTools;
|
|
46
|
+
type HandlersRequirements<H> = H extends Record<string, (...args: ReadonlyArray<unknown>) => Effect.Effect<unknown, unknown, infer R>> ? Exclude<R, RuntimeRequirements> : never;
|
|
45
47
|
/**
|
|
46
48
|
* @since 0.1.0
|
|
47
49
|
* @category models
|
|
48
50
|
*/
|
|
49
|
-
type HandlerRequirements<Handler> = Handler extends ((...args: ReadonlyArray<unknown>) => Effect.Effect<unknown, unknown, infer R>) ? R : never;
|
|
51
|
+
type HandlerRequirements<Handler> = Handler extends ((...args: ReadonlyArray<unknown>) => Effect.Effect<unknown, unknown, infer R>) ? Exclude<R, RuntimeRequirements> : never;
|
|
50
52
|
/**
|
|
51
53
|
* A nominal type representing a registered handler for a specific function tag.
|
|
52
54
|
* @since 0.1.0
|
|
@@ -63,7 +65,7 @@ interface Handler<Tag extends string> {
|
|
|
63
65
|
* @since 0.1.0
|
|
64
66
|
* @category models
|
|
65
67
|
*/
|
|
66
|
-
type ToHandler<F extends InngestFunction.Any> = F extends InngestFunction<infer Tag, infer _Triggers
|
|
68
|
+
type ToHandler<F extends InngestFunction.Any> = F extends InngestFunction<infer Tag, infer _Triggers> ? Handler<Tag> : never;
|
|
67
69
|
/**
|
|
68
70
|
* @since 0.1.0
|
|
69
71
|
* @category models
|
|
@@ -88,9 +90,7 @@ interface InngestGroup<Fns extends InngestFunction.Any> {
|
|
|
88
90
|
*/
|
|
89
91
|
readonly accessHandler: <Tag extends InngestFunction.Tag<Fns>>(tag: Tag) => Effect.Effect<(context: HandlerContext<Extract<Fns, {
|
|
90
92
|
readonly _tag: Tag;
|
|
91
|
-
}>>) => Effect.Effect<
|
|
92
|
-
readonly _tag: Tag;
|
|
93
|
-
}>>, unknown>, never, Handler<Tag>>;
|
|
93
|
+
}>>) => Effect.Effect<unknown, unknown>, never, Handler<Tag>>;
|
|
94
94
|
}
|
|
95
95
|
/**
|
|
96
96
|
* @since 0.1.0
|
package/dist/Group.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { __exportAll } from "./_virtual/_rolldown/runtime.js";
|
|
2
|
+
import "./internal/runtime/StepTools.js";
|
|
2
3
|
import "./internal/runtime/HandlerContext.js";
|
|
3
4
|
import { toHttpApp as toHttpApp$1, toWebHandler as toWebHandler$1 } from "./internal/serve/HttpApp.js";
|
|
4
5
|
import { Context, Effect, Layer } from "effect";
|
package/dist/HttpApi.js
CHANGED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { InngestClient } from "./Client.js";
|
|
2
|
+
import { EventType as EventType$1 } from "./Event.js";
|
|
3
|
+
import { InngestFunction } from "./Function.js";
|
|
4
|
+
import { EventSchema } from "./internal/codec/EventPayload.js";
|
|
5
|
+
import { SendEventError, StepError } from "./internal/errors.js";
|
|
6
|
+
import { StepInput } from "./internal/domain/StepInput.js";
|
|
7
|
+
import { InvokeOptions, OutgoingEvent, StepTools, WaitForEventOptions } from "./internal/runtime/StepTools.js";
|
|
8
|
+
import { Duration, Effect, Option } from "effect";
|
|
9
|
+
|
|
10
|
+
//#region src/Inngest.d.ts
|
|
11
|
+
declare namespace Inngest_d_exports {
|
|
12
|
+
export { EventType, invoke, run, sendEvent, sleep, sleepUntil, waitForEvent };
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Execute an Effect as a durable, memoized step.
|
|
16
|
+
*
|
|
17
|
+
* @since 0.1.0
|
|
18
|
+
* @category steps
|
|
19
|
+
*/
|
|
20
|
+
declare const run: <A, Err, R>(id: StepInput, effect: Effect.Effect<A, Err, R>) => Effect.Effect<A, StepError | Err, R | StepTools>;
|
|
21
|
+
/**
|
|
22
|
+
* Sleep durably for a duration.
|
|
23
|
+
*
|
|
24
|
+
* @since 0.1.0
|
|
25
|
+
* @category steps
|
|
26
|
+
*/
|
|
27
|
+
declare const sleep: (id: StepInput, duration: Duration.Input) => Effect.Effect<void, never, StepTools>;
|
|
28
|
+
/**
|
|
29
|
+
* Sleep durably until a timestamp.
|
|
30
|
+
*
|
|
31
|
+
* @since 0.1.0
|
|
32
|
+
* @category steps
|
|
33
|
+
*/
|
|
34
|
+
declare const sleepUntil: (id: StepInput, timestamp: Date | number | string) => Effect.Effect<void, never, StepTools>;
|
|
35
|
+
/**
|
|
36
|
+
* Wait for a matching event.
|
|
37
|
+
*
|
|
38
|
+
* @since 0.1.0
|
|
39
|
+
* @category steps
|
|
40
|
+
*/
|
|
41
|
+
declare const waitForEvent: <E extends EventSchema>(id: StepInput, event: E, options: WaitForEventOptions) => Effect.Effect<Option.Option<EventType$1<E>>, StepError, StepTools>;
|
|
42
|
+
/**
|
|
43
|
+
* Invoke another Inngest function.
|
|
44
|
+
*
|
|
45
|
+
* @since 0.1.0
|
|
46
|
+
* @category steps
|
|
47
|
+
*/
|
|
48
|
+
declare const invoke: <F extends InngestFunction.Any>(id: StepInput, options: InvokeOptions<F>) => Effect.Effect<unknown, StepError, StepTools>;
|
|
49
|
+
/**
|
|
50
|
+
* Send one or more Inngest events.
|
|
51
|
+
*
|
|
52
|
+
* @since 0.1.0
|
|
53
|
+
* @category steps
|
|
54
|
+
*/
|
|
55
|
+
declare const sendEvent: (id: StepInput, payload: OutgoingEvent | ReadonlyArray<OutgoingEvent>) => Effect.Effect<{
|
|
56
|
+
readonly ids: ReadonlyArray<string>;
|
|
57
|
+
}, SendEventError, StepTools | InngestClient>;
|
|
58
|
+
type EventType<E extends EventSchema> = EventType$1<E>;
|
|
59
|
+
//#endregion
|
|
60
|
+
export { Inngest_d_exports };
|
package/dist/Inngest.js
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { __exportAll } from "./_virtual/_rolldown/runtime.js";
|
|
2
|
+
import { StepTools } from "./internal/runtime/StepTools.js";
|
|
3
|
+
import { Effect } from "effect";
|
|
4
|
+
//#region src/Inngest.ts
|
|
5
|
+
/**
|
|
6
|
+
* Durable workflow operations for Inngest handlers.
|
|
7
|
+
*
|
|
8
|
+
* @since 0.1.0
|
|
9
|
+
*/
|
|
10
|
+
var Inngest_exports = /* @__PURE__ */ __exportAll({
|
|
11
|
+
invoke: () => invoke,
|
|
12
|
+
run: () => run,
|
|
13
|
+
sendEvent: () => sendEvent,
|
|
14
|
+
sleep: () => sleep,
|
|
15
|
+
sleepUntil: () => sleepUntil,
|
|
16
|
+
waitForEvent: () => waitForEvent
|
|
17
|
+
});
|
|
18
|
+
/**
|
|
19
|
+
* Execute an Effect as a durable, memoized step.
|
|
20
|
+
*
|
|
21
|
+
* @since 0.1.0
|
|
22
|
+
* @category steps
|
|
23
|
+
*/
|
|
24
|
+
const run = (id, effect) => Effect.flatMap(StepTools, (step) => step.run(id, effect));
|
|
25
|
+
/**
|
|
26
|
+
* Sleep durably for a duration.
|
|
27
|
+
*
|
|
28
|
+
* @since 0.1.0
|
|
29
|
+
* @category steps
|
|
30
|
+
*/
|
|
31
|
+
const sleep = (id, duration) => Effect.flatMap(StepTools, (step) => step.sleep(id, duration));
|
|
32
|
+
/**
|
|
33
|
+
* Sleep durably until a timestamp.
|
|
34
|
+
*
|
|
35
|
+
* @since 0.1.0
|
|
36
|
+
* @category steps
|
|
37
|
+
*/
|
|
38
|
+
const sleepUntil = (id, timestamp) => Effect.flatMap(StepTools, (step) => step.sleepUntil(id, timestamp));
|
|
39
|
+
/**
|
|
40
|
+
* Wait for a matching event.
|
|
41
|
+
*
|
|
42
|
+
* @since 0.1.0
|
|
43
|
+
* @category steps
|
|
44
|
+
*/
|
|
45
|
+
const waitForEvent = (id, event, options) => Effect.flatMap(StepTools, (step) => step.waitForEvent(id, event, options));
|
|
46
|
+
/**
|
|
47
|
+
* Invoke another Inngest function.
|
|
48
|
+
*
|
|
49
|
+
* @since 0.1.0
|
|
50
|
+
* @category steps
|
|
51
|
+
*/
|
|
52
|
+
const invoke = (id, options) => Effect.flatMap(StepTools, (step) => step.invoke(id, options));
|
|
53
|
+
/**
|
|
54
|
+
* Send one or more Inngest events.
|
|
55
|
+
*
|
|
56
|
+
* @since 0.1.0
|
|
57
|
+
* @category steps
|
|
58
|
+
*/
|
|
59
|
+
const sendEvent = (id, payload) => Effect.flatMap(StepTools, (step) => step.sendEvent(id, payload));
|
|
60
|
+
//#endregion
|
|
61
|
+
export { Inngest_exports };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { Client_d_exports } from "./Client.js";
|
|
2
2
|
import { Event_d_exports } from "./Event.js";
|
|
3
3
|
import { Events_d_exports } from "./Events.js";
|
|
4
|
+
import { Cron_d_exports } from "./Cron.js";
|
|
4
5
|
import { Function_d_exports } from "./Function.js";
|
|
5
6
|
import { NonRetriableError, RetryAfterError } from "./internal/errors.js";
|
|
6
7
|
import { Group_d_exports } from "./Group.js";
|
|
7
8
|
import { HttpApi_d_exports } from "./HttpApi.js";
|
|
8
|
-
|
|
9
|
+
import { Inngest_d_exports } from "./Inngest.js";
|
|
10
|
+
export { Inngest_d_exports as Inngest, Client_d_exports as InngestClient, Cron_d_exports as InngestCron, Event_d_exports as InngestEvent, Events_d_exports as InngestEvents, Function_d_exports as InngestFunction, Group_d_exports as InngestGroup, HttpApi_d_exports as InngestHttpApi, NonRetriableError, RetryAfterError };
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import { Function_exports } from "./Function.js";
|
|
2
1
|
import { Event_exports } from "./Event.js";
|
|
2
|
+
import { Cron_exports } from "./Cron.js";
|
|
3
|
+
import { Function_exports } from "./Function.js";
|
|
3
4
|
import { Client_exports } from "./Client.js";
|
|
4
5
|
import { NonRetriableError, RetryAfterError } from "./internal/errors.js";
|
|
5
6
|
import { Events_exports } from "./Events.js";
|
|
6
7
|
import { Group_exports } from "./Group.js";
|
|
8
|
+
import { Inngest_exports } from "./Inngest.js";
|
|
7
9
|
import { HttpApi_exports } from "./HttpApi.js";
|
|
8
|
-
export { Client_exports as InngestClient, Event_exports as InngestEvent, Events_exports as InngestEvents, Function_exports as InngestFunction, Group_exports as InngestGroup, HttpApi_exports as InngestHttpApi, NonRetriableError, RetryAfterError };
|
|
10
|
+
export { Inngest_exports as Inngest, Client_exports as InngestClient, Cron_exports as InngestCron, Event_exports as InngestEvent, Events_exports as InngestEvents, Function_exports as InngestFunction, Group_exports as InngestGroup, HttpApi_exports as InngestHttpApi, NonRetriableError, RetryAfterError };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import { Effect } from "effect";
|
|
1
|
+
import { Effect, Option } from "effect";
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { StaleDispatch } from "./Abort.js";
|
|
1
2
|
import { Array, Clock, Duration, Effect, Option, Ref, Result } from "effect";
|
|
2
3
|
//#region src/internal/checkpoint/State.ts
|
|
3
4
|
const make = (args) => Effect.sync(() => {
|
|
@@ -5,12 +6,17 @@ const make = (args) => Effect.sync(() => {
|
|
|
5
6
|
const plannedBuffer = Ref.makeUnsafe(Array.empty());
|
|
6
7
|
const intervalStartedAt = Ref.makeUnsafe(Option.none());
|
|
7
8
|
const runtimeExceeded = Ref.makeUnsafe(false);
|
|
9
|
+
const abort = Ref.makeUnsafe(Option.none());
|
|
8
10
|
const maxIntervalMs = Duration.toMillis(args.config.maxInterval);
|
|
9
11
|
const flushInner = Effect.gen(function* () {
|
|
10
12
|
const steps = yield* Ref.modify(buffer, (current) => [current, Array.empty()]);
|
|
11
13
|
if (steps.length === 0) return;
|
|
12
14
|
const result = yield* Effect.result(args.checkpointAsync(steps));
|
|
13
15
|
if (Result.isFailure(result)) {
|
|
16
|
+
if (result.failure.status === 409) {
|
|
17
|
+
yield* Ref.set(abort, Option.some(StaleDispatch.make({})));
|
|
18
|
+
return yield* Effect.interrupt;
|
|
19
|
+
}
|
|
14
20
|
yield* Ref.update(buffer, (current) => [...steps, ...current]);
|
|
15
21
|
return;
|
|
16
22
|
}
|
|
@@ -47,7 +53,8 @@ const make = (args) => Effect.sync(() => {
|
|
|
47
53
|
flush: flushInner,
|
|
48
54
|
takeCompleted,
|
|
49
55
|
markRuntimeExceeded: Ref.set(runtimeExceeded, true),
|
|
50
|
-
isRuntimeExceeded: Ref.get(runtimeExceeded)
|
|
56
|
+
isRuntimeExceeded: Ref.get(runtimeExceeded),
|
|
57
|
+
abort: Ref.get(abort)
|
|
51
58
|
};
|
|
52
59
|
});
|
|
53
60
|
//#endregion
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { StepError } from "../errors.js";
|
|
2
|
-
import { Effect, Function,
|
|
2
|
+
import { Effect, Function, Predicate } from "effect";
|
|
3
3
|
//#region src/internal/codec/StepResult.ts
|
|
4
4
|
const messageFromCause = (cause) => {
|
|
5
5
|
if (Predicate.hasProperty(cause, "cause")) {
|
|
@@ -25,16 +25,6 @@ const mapMemoDecodeError = Function.dual(2, (effect, stepId) => effect.pipe(Effe
|
|
|
25
25
|
stepId,
|
|
26
26
|
cause
|
|
27
27
|
}))));
|
|
28
|
-
const decodeMemo = Function.dual(3, (value, schema, stepId) => Schema.decodeUnknownEffect(schema)(value).pipe(mapMemoDecodeError(stepId)));
|
|
29
|
-
const encodeMemo = Function.dual(3, (value, schema, stepId) => Schema.encodeUnknownEffect(Schema.toCodecJson(schema))(value).pipe(mapMemoDecodeError(stepId)));
|
|
30
|
-
const decodeStepRunMemo = (schema, stepId) => (value) => Option.match(schema, {
|
|
31
|
-
onNone: () => Effect.void,
|
|
32
|
-
onSome: (codec) => decodeMemo(codec, stepId)(value)
|
|
33
|
-
});
|
|
34
|
-
const encodeStepRunMemo = (schema, stepId) => (value) => Option.match(schema, {
|
|
35
|
-
onNone: () => Predicate.isUndefined(value) ? Effect.succeed(void 0) : decodeMemo(Schema.Json, stepId)(value),
|
|
36
|
-
onSome: (codec) => encodeMemo(codec, stepId)(value)
|
|
37
|
-
});
|
|
38
28
|
const failStepRunMemoError = (stepId, error) => Effect.fail(StepError.make({
|
|
39
29
|
stepId,
|
|
40
30
|
message: Predicate.hasProperty(error, "message") ? String(error.message) : "Step failed",
|
|
@@ -52,4 +42,4 @@ const failUnexpectedStepRunMemoInput = (stepId, input) => Effect.fail(StepError.
|
|
|
52
42
|
cause: input
|
|
53
43
|
}));
|
|
54
44
|
//#endregion
|
|
55
|
-
export {
|
|
45
|
+
export { failMemoDecode, failStepRunMemoError, failStepRunMemoTimeout, failUnexpectedStepRunMemoInput, mapMemoDecodeError };
|
package/dist/internal/driver.js
CHANGED
package/dist/internal/errors.js
CHANGED
|
@@ -21,6 +21,6 @@ var RetryAfterError = class extends Schema.TaggedErrorClass()("RetryAfterError",
|
|
|
21
21
|
retryAfter: Schema.DurationFromMillis,
|
|
22
22
|
cause: Schema.optional(Schema.Unknown)
|
|
23
23
|
}) {};
|
|
24
|
-
const isRetryAfterError =
|
|
24
|
+
const isRetryAfterError = Schema.is(RetryAfterError);
|
|
25
25
|
//#endregion
|
|
26
26
|
export { NonRetriableError, RetryAfterError, SendEventError, StepError, isNonRetriableError, isRetryAfterError, isStepError };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { GeneratorOpcode } from "../protocol.js";
|
|
2
2
|
import { InngestConfig } from "../../Client.js";
|
|
3
3
|
import { CurrentCheckpoint } from "../runtime/CheckpointContext.js";
|
|
4
|
+
import { StepError } from "../errors.js";
|
|
4
5
|
import { StepCommandBus } from "../runtime/StepCommandBus.js";
|
|
5
6
|
import { ExecutionFailure } from "./ExecutionFailure.js";
|
|
6
7
|
import { RetryDisposition, base } from "./ExecutionHeaders.js";
|
|
@@ -23,7 +24,27 @@ const fromSuccess = (args) => Effect.gen(function* () {
|
|
|
23
24
|
headers: args.headers
|
|
24
25
|
})), Match.tag("CheckpointDeadlineElapsed", () => ExecutionResult.checkpointDeadlineOutsideCheckpoint(args)), Match.exhaustive);
|
|
25
26
|
});
|
|
27
|
+
const fromCheckpointAbort = (args) => Match.value(args.abort).pipe(Match.tag("StaleDispatch", () => {
|
|
28
|
+
const error = new StepError({
|
|
29
|
+
stepId: "checkpoint",
|
|
30
|
+
message: "Stale dispatch: checkpoint returned 409",
|
|
31
|
+
noRetry: true
|
|
32
|
+
});
|
|
33
|
+
return ExecutionResult.userError({
|
|
34
|
+
error,
|
|
35
|
+
headers: args.headers,
|
|
36
|
+
disposition: RetryDisposition.fromError(error)
|
|
37
|
+
});
|
|
38
|
+
}), Match.exhaustive);
|
|
26
39
|
const fromFailure = (args) => Effect.gen(function* () {
|
|
40
|
+
const checkpoint = yield* CurrentCheckpoint;
|
|
41
|
+
if (Cause.hasInterruptsOnly(args.cause) && Option.isSome(checkpoint)) {
|
|
42
|
+
const abort = yield* checkpoint.value.abort;
|
|
43
|
+
if (Option.isSome(abort)) return fromCheckpointAbort({
|
|
44
|
+
abort: abort.value,
|
|
45
|
+
headers: args.headers
|
|
46
|
+
});
|
|
47
|
+
}
|
|
27
48
|
const commands = yield* (yield* StepCommandBus).takeSuspension();
|
|
28
49
|
if (commands.suspendedCount > 0 && Cause.hasInterruptsOnly(args.cause)) return ExecutionResult.opcodesWithRetry({
|
|
29
50
|
opcodes: commands.opcodes,
|
|
@@ -45,10 +66,18 @@ const fromFailure = (args) => Effect.gen(function* () {
|
|
|
45
66
|
});
|
|
46
67
|
});
|
|
47
68
|
const fromExit = (exit) => Effect.gen(function* () {
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
69
|
+
const headers = base(yield* InngestConfig);
|
|
70
|
+
if (Exit.isFailure(exit) && Cause.hasInterruptsOnly(exit.cause)) {
|
|
71
|
+
const checkpoint = yield* CurrentCheckpoint;
|
|
72
|
+
if (Option.isSome(checkpoint)) {
|
|
73
|
+
const abort = yield* checkpoint.value.abort;
|
|
74
|
+
if (Option.isSome(abort)) return fromCheckpointAbort({
|
|
75
|
+
abort: abort.value,
|
|
76
|
+
headers
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
const planned = yield* (yield* StepCommandBus).takePlanned();
|
|
52
81
|
if (planned.length > 0) return ExecutionResult.opcodes({
|
|
53
82
|
opcodes: planned,
|
|
54
83
|
headers
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { CurrentCheckpoint } from "../runtime/CheckpointContext.js";
|
|
2
|
+
import { normalize } from "../utils/safe-stringify.js";
|
|
2
3
|
import { make } from "../runtime/HandlerContext.js";
|
|
3
4
|
import { Effect, Option, Schema } from "effect";
|
|
4
5
|
//#region src/internal/execution/HandlerRun.ts
|
|
5
6
|
var HandlerSucceeded = class extends Schema.TaggedClass()("HandlerSucceeded", { value: Schema.Unknown }) {};
|
|
6
7
|
Schema.TaggedClass()("CheckpointDeadlineElapsed", {});
|
|
7
|
-
const run = (args) => make({ fn: args.fn }).pipe(Effect.flatMap(args.handler), Effect.map((value) => HandlerSucceeded.make({ value })));
|
|
8
|
+
const run = (args) => make({ fn: args.fn }).pipe(Effect.flatMap(args.handler), Effect.map((value) => HandlerSucceeded.make({ value: normalize(value) })));
|
|
8
9
|
const withCheckpointDeadline = (effect) => Effect.gen(function* () {
|
|
9
10
|
const checkpoint = yield* CurrentCheckpoint;
|
|
10
11
|
return yield* Option.match(checkpoint, {
|
package/dist/internal/handler.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { resolveConfig } from "./checkpoint/Config.js";
|
|
2
|
-
import { Headers, RegisterServerResponse, SDKRequestBody, SDKRequestContext, UserError } from "./protocol.js";
|
|
2
|
+
import { Headers as Headers$1, RegisterServerResponse, SDKRequestBody, SDKRequestContext, UserError } from "./protocol.js";
|
|
3
3
|
import "./serve/Signature.js";
|
|
4
4
|
import { InngestClient } from "../Client.js";
|
|
5
5
|
import { schemaBodyJson, verifySignature } from "./serve/Request.js";
|
|
@@ -9,16 +9,17 @@ import * as HttpClient from "effect/unstable/http/HttpClient";
|
|
|
9
9
|
import * as HttpClientRequest from "effect/unstable/http/HttpClientRequest";
|
|
10
10
|
import * as HttpClientResponse from "effect/unstable/http/HttpClientResponse";
|
|
11
11
|
import "effect/unstable/http/HttpServerRequest";
|
|
12
|
+
import * as Headers from "effect/unstable/http/Headers";
|
|
12
13
|
//#region src/internal/handler.ts
|
|
13
14
|
var InvalidRequestError = class extends Schema.TaggedErrorClass()("InvalidRequestError", { message: Schema.String }) {};
|
|
14
15
|
const SDK_VERSION = "2.0.0";
|
|
15
16
|
const baseHeaders = (framework) => ({
|
|
16
17
|
"Content-Type": "application/json",
|
|
17
18
|
"User-Agent": `effect-inngest:v${SDK_VERSION}`,
|
|
18
|
-
[Headers.SDK]: `effect-inngest:v${SDK_VERSION}`,
|
|
19
|
-
[Headers.SDKHandled]: "true",
|
|
20
|
-
[Headers.RequestVersion]: "2",
|
|
21
|
-
...framework ? { [Headers.Framework]: framework } : {}
|
|
19
|
+
[Headers$1.SDK]: `effect-inngest:v${SDK_VERSION}`,
|
|
20
|
+
[Headers$1.SDKHandled]: "true",
|
|
21
|
+
[Headers$1.RequestVersion]: "2",
|
|
22
|
+
...framework ? { [Headers$1.Framework]: framework } : {}
|
|
22
23
|
});
|
|
23
24
|
const buildServeUrl = (args) => {
|
|
24
25
|
const url = new URL(args.requestUrl);
|
|
@@ -66,11 +67,11 @@ const handleRegistration = Effect.fn("effect-inngest/handler/handleRegistration"
|
|
|
66
67
|
const framework = config.framework;
|
|
67
68
|
const registerUrl = new URL("fn/register", client.apiBaseUrl).toString();
|
|
68
69
|
const registerHeaders = baseHeaders(framework);
|
|
69
|
-
delete registerHeaders[Headers.RequestVersion];
|
|
70
|
+
delete registerHeaders[Headers$1.RequestVersion];
|
|
70
71
|
const request = HttpClientRequest.post(registerUrl).pipe(HttpClientRequest.setHeaders({
|
|
71
72
|
...registerHeaders,
|
|
72
73
|
Authorization: `Bearer ${config.signingKey ?? ""}`,
|
|
73
|
-
[Headers.SyncKind]: "out_of_band"
|
|
74
|
+
[Headers$1.SyncKind]: "out_of_band"
|
|
74
75
|
}), HttpClientRequest.bodyJsonUnsafe({
|
|
75
76
|
url: url.href,
|
|
76
77
|
deployType: "ping",
|
|
@@ -99,7 +100,7 @@ const handleRegistration = Effect.fn("effect-inngest/handler/handleRegistration"
|
|
|
99
100
|
status: 200,
|
|
100
101
|
headers: {
|
|
101
102
|
...baseHeaders(config.framework),
|
|
102
|
-
[Headers.SyncKind]: "out_of_band"
|
|
103
|
+
[Headers$1.SyncKind]: "out_of_band"
|
|
103
104
|
},
|
|
104
105
|
body: {
|
|
105
106
|
message: "Successfully registered",
|
|
@@ -131,7 +132,7 @@ const handleExecution = Effect.fn("effect-inngest/handler/handleExecution")(func
|
|
|
131
132
|
status: 500,
|
|
132
133
|
headers: {
|
|
133
134
|
...baseHeaders(client.config.framework),
|
|
134
|
-
[Headers.NoRetry]: "false"
|
|
135
|
+
[Headers$1.NoRetry]: "false"
|
|
135
136
|
},
|
|
136
137
|
body: UserError.make({
|
|
137
138
|
name: "FunctionNotFoundError",
|
|
@@ -139,27 +140,39 @@ const handleExecution = Effect.fn("effect-inngest/handler/handleExecution")(func
|
|
|
139
140
|
})
|
|
140
141
|
};
|
|
141
142
|
const requestedStepId = args.urlStepId === "step" ? void 0 : args.urlStepId;
|
|
143
|
+
const requestId = (args.headers ? Option.getOrUndefined(Headers.get(args.headers, Headers$1.RequestId)) : void 0) ?? args.body.ctx.request_id;
|
|
144
|
+
const rawGenerationId = args.headers ? Option.getOrUndefined(Headers.get(args.headers, Headers$1.GenerationId)) : void 0;
|
|
145
|
+
const parsedGenerationId = rawGenerationId ? Number(rawGenerationId) : void 0;
|
|
146
|
+
const generationId = Predicate.isNumber(parsedGenerationId) && Number.isInteger(parsedGenerationId) ? parsedGenerationId : args.body.ctx.generation_id;
|
|
147
|
+
const withExecutionHeaders = (ctx) => SDKRequestContext.make({
|
|
148
|
+
fn_id: ctx.fn_id,
|
|
149
|
+
run_id: ctx.run_id,
|
|
150
|
+
env: ctx.env,
|
|
151
|
+
step_id: requestedStepId ?? ctx.step_id,
|
|
152
|
+
attempt: ctx.attempt,
|
|
153
|
+
max_attempts: ctx.max_attempts,
|
|
154
|
+
qi_id: ctx.qi_id,
|
|
155
|
+
...Predicate.isNotUndefined(requestId) ? { request_id: requestId } : {},
|
|
156
|
+
...Predicate.isNotUndefined(generationId) ? { generation_id: generationId } : {},
|
|
157
|
+
disable_immediate_execution: ctx.disable_immediate_execution,
|
|
158
|
+
use_api: ctx.use_api,
|
|
159
|
+
stack: ctx.stack
|
|
160
|
+
});
|
|
142
161
|
const effectiveBody = requestedStepId && requestedStepId !== args.body.ctx.step_id ? SDKRequestBody.make({
|
|
143
162
|
event: args.body.event,
|
|
144
163
|
events: args.body.events,
|
|
145
164
|
steps: args.body.steps,
|
|
146
|
-
ctx:
|
|
147
|
-
fn_id: args.body.ctx.fn_id,
|
|
148
|
-
run_id: args.body.ctx.run_id,
|
|
149
|
-
env: args.body.ctx.env,
|
|
150
|
-
step_id: requestedStepId,
|
|
151
|
-
attempt: args.body.ctx.attempt,
|
|
152
|
-
max_attempts: args.body.ctx.max_attempts,
|
|
153
|
-
qi_id: args.body.ctx.qi_id,
|
|
154
|
-
...Predicate.isNotUndefined(args.body.ctx.request_id) ? { request_id: args.body.ctx.request_id } : {},
|
|
155
|
-
...Predicate.isNotUndefined(args.body.ctx.generation_id) ? { generation_id: args.body.ctx.generation_id } : {},
|
|
156
|
-
disable_immediate_execution: args.body.ctx.disable_immediate_execution,
|
|
157
|
-
use_api: args.body.ctx.use_api,
|
|
158
|
-
stack: args.body.ctx.stack
|
|
159
|
-
}),
|
|
165
|
+
ctx: withExecutionHeaders(args.body.ctx),
|
|
160
166
|
version: args.body.version,
|
|
161
167
|
use_api: args.body.use_api
|
|
162
|
-
}) :
|
|
168
|
+
}) : SDKRequestBody.make({
|
|
169
|
+
event: args.body.event,
|
|
170
|
+
events: args.body.events,
|
|
171
|
+
steps: args.body.steps,
|
|
172
|
+
ctx: withExecutionHeaders(args.body.ctx),
|
|
173
|
+
version: args.body.version,
|
|
174
|
+
use_api: args.body.use_api
|
|
175
|
+
});
|
|
163
176
|
const checkpointConfig = !requestedStepId && effectiveBody.ctx.fn_id !== "" && !effectiveBody.ctx.disable_immediate_execution && effectiveBody.ctx.attempt === 0 ? Option.fromNullishOr(resolveConfig(fn.options.checkpointing, client.config.checkpointing)) : Option.none();
|
|
164
177
|
const result = yield* Effect.provide(execute({
|
|
165
178
|
fn,
|
|
@@ -90,6 +90,9 @@ const Headers = {
|
|
|
90
90
|
SyncKind: "x-inngest-sync-kind",
|
|
91
91
|
ServerKind: "X-Inngest-Server-Kind",
|
|
92
92
|
ExpectedServerKind: "X-Inngest-Expected-Server-Kind",
|
|
93
|
+
RequestId: "x-request-id",
|
|
94
|
+
GenerationId: "x-inngest-generation-id",
|
|
95
|
+
JobId: "x-inngest-job-id",
|
|
93
96
|
RunID: "X-Run-ID",
|
|
94
97
|
Framework: "X-Inngest-Framework",
|
|
95
98
|
Platform: "X-Inngest-Platform",
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import { InngestFunction } from "../../Function.js";
|
|
2
2
|
import { ExecutionInput } from "../domain/ExecutionInput.js";
|
|
3
|
-
import { StepTools } from "./StepTools.js";
|
|
4
3
|
import { Effect } from "effect";
|
|
5
4
|
|
|
6
5
|
//#region src/internal/runtime/HandlerContext.d.ts
|
|
7
6
|
interface HandlerContext<F extends InngestFunction.Any = InngestFunction.Any> {
|
|
8
7
|
readonly event: InngestFunction.EventType<F>;
|
|
9
|
-
readonly step: StepTools.Service;
|
|
10
8
|
readonly run: ExecutionInput["run"];
|
|
11
9
|
}
|
|
12
10
|
//#endregion
|
|
@@ -1,17 +1,14 @@
|
|
|
1
1
|
import { CurrentExecutionInput } from "../domain/ExecutionInput.js";
|
|
2
2
|
import { decodeInvocation } from "../codec/EventPayload.js";
|
|
3
|
-
import { StepTools } from "./StepTools.js";
|
|
4
3
|
import { Effect } from "effect";
|
|
5
4
|
//#region src/internal/runtime/HandlerContext.ts
|
|
6
5
|
const make = (args) => Effect.gen(function* () {
|
|
7
6
|
const input = yield* CurrentExecutionInput;
|
|
8
|
-
const step = yield* StepTools;
|
|
9
7
|
return {
|
|
10
8
|
event: yield* decodeInvocation({
|
|
11
9
|
fn: args.fn,
|
|
12
10
|
input
|
|
13
11
|
}),
|
|
14
|
-
step,
|
|
15
12
|
run: input.run
|
|
16
13
|
};
|
|
17
14
|
});
|
|
@@ -8,13 +8,9 @@ import { StepInput } from "../domain/StepInput.js";
|
|
|
8
8
|
import { HandlerFiberScope } from "./HandlerFiberScope.js";
|
|
9
9
|
import { StepCommandBus } from "./StepCommandBus.js";
|
|
10
10
|
import { StepIdentity } from "./StepIdentity.js";
|
|
11
|
-
import { Context, Duration, Effect, Layer, Option
|
|
11
|
+
import { Context, Duration, Effect, Layer, Option } from "effect";
|
|
12
12
|
|
|
13
13
|
//#region src/internal/runtime/StepTools.d.ts
|
|
14
|
-
type JsonSchema<A = unknown> = Schema.Codec<A, unknown, never, never>;
|
|
15
|
-
interface RunOptions<S extends JsonSchema> {
|
|
16
|
-
readonly schema: S;
|
|
17
|
-
}
|
|
18
14
|
interface WaitForEventOptions {
|
|
19
15
|
readonly timeout: Duration.Input;
|
|
20
16
|
readonly if?: string;
|
|
@@ -29,8 +25,7 @@ type InvokeOptions<F extends InngestFunction.Any> = [InngestFunction.EventPayloa
|
|
|
29
25
|
readonly data: InngestFunction.EventPayload<F>;
|
|
30
26
|
};
|
|
31
27
|
interface Run {
|
|
32
|
-
<Err, R>(id: StepInput, effect: Effect.Effect<
|
|
33
|
-
<S extends JsonSchema, Err, R>(id: StepInput, effect: Effect.Effect<Schema.Schema.Type<S>, Err, R>, options: RunOptions<S>): Effect.Effect<Schema.Schema.Type<S>, StepError | Err, R>;
|
|
28
|
+
<A, Err, R>(id: StepInput, effect: Effect.Effect<A, Err, R>): Effect.Effect<A, StepError | Err, R>;
|
|
34
29
|
}
|
|
35
30
|
interface Sleep {
|
|
36
31
|
(id: StepInput, duration: Duration.Input): Effect.Effect<void>;
|
|
@@ -42,7 +37,7 @@ interface WaitForEvent {
|
|
|
42
37
|
<E extends EventSchema>(id: StepInput, event: E, options: WaitForEventOptions): Effect.Effect<Option.Option<EventType<E>>, StepError>;
|
|
43
38
|
}
|
|
44
39
|
interface Invoke {
|
|
45
|
-
<F extends InngestFunction.Any>(id: StepInput, options: InvokeOptions<F>): Effect.Effect<
|
|
40
|
+
<F extends InngestFunction.Any>(id: StepInput, options: InvokeOptions<F>): Effect.Effect<unknown, StepError>;
|
|
46
41
|
}
|
|
47
42
|
interface OutgoingEvent {
|
|
48
43
|
readonly name: string;
|
|
@@ -66,18 +61,15 @@ declare namespace StepTools {
|
|
|
66
61
|
declare const StepTools_base: Context.ServiceClass<StepTools, "effect-inngest/internal/runtime/StepTools", StepTools.Service>;
|
|
67
62
|
declare class StepTools extends StepTools_base {
|
|
68
63
|
static readonly make: Effect.Effect<{
|
|
69
|
-
run:
|
|
70
|
-
<Err, R>(id: StepInput, effect: Effect.Effect<void, Err, R>): Effect.Effect<void, StepError | Err, R>;
|
|
71
|
-
<S extends JsonSchema, Err, R>(id: StepInput, effect: Effect.Effect<Schema.Schema.Type<S>, Err, R>, options: RunOptions<S>): Effect.Effect<Schema.Schema.Type<S>, StepError | Err, R>;
|
|
72
|
-
};
|
|
64
|
+
run: <A, Err, R>(id: StepInput, effect: Effect.Effect<A, Err, R>) => Effect.Effect<A, StepError | Err, Exclude<R, CurrentExecutionInput | HandlerFiberScope | InngestConfig | StepCommandBus | StepIdentity>>;
|
|
73
65
|
sleep: Sleep;
|
|
74
66
|
sleepUntil: SleepUntil;
|
|
75
67
|
waitForEvent: WaitForEvent;
|
|
76
68
|
invoke: Invoke;
|
|
77
69
|
sendEvent: SendEvent;
|
|
78
|
-
}, never,
|
|
79
|
-
static readonly layer: Layer.Layer<StepTools, never,
|
|
80
|
-
static readonly live: Layer.Layer<StepTools, never,
|
|
70
|
+
}, never, CurrentExecutionInput | HandlerFiberScope | InngestConfig | StepCommandBus | StepIdentity>;
|
|
71
|
+
static readonly layer: Layer.Layer<StepTools, never, CurrentExecutionInput | HandlerFiberScope | InngestConfig | StepCommandBus | StepIdentity>;
|
|
72
|
+
static readonly live: Layer.Layer<StepTools, never, CurrentExecutionInput | HandlerFiberScope | InngestConfig | StepIdentity>;
|
|
81
73
|
}
|
|
82
74
|
//#endregion
|
|
83
|
-
export { StepTools };
|
|
75
|
+
export { InvokeOptions, OutgoingEvent, StepTools, WaitForEventOptions };
|
|
@@ -10,7 +10,7 @@ import { sleep } from "./steps/SleepStep.js";
|
|
|
10
10
|
import { sleepUntil } from "./steps/SleepUntilStep.js";
|
|
11
11
|
import { run } from "./steps/StepRun.js";
|
|
12
12
|
import { waitForEvent } from "./steps/WaitForEventStep.js";
|
|
13
|
-
import { Context, Effect, Layer,
|
|
13
|
+
import { Context, Effect, Layer, pipe } from "effect";
|
|
14
14
|
//#region src/internal/runtime/StepTools.ts
|
|
15
15
|
var StepTools = class extends Context.Service()("effect-inngest/internal/runtime/StepTools") {
|
|
16
16
|
static make = Effect.gen(function* () {
|
|
@@ -21,13 +21,7 @@ var StepTools = class extends Context.Service()("effect-inngest/internal/runtime
|
|
|
21
21
|
const bus = yield* StepCommandBus;
|
|
22
22
|
const handlerFiberScope = yield* HandlerFiberScope;
|
|
23
23
|
const runtime = pipe(Context.make(StepIdentity, identity), Context.add(StepCommandBus, bus), Context.add(CurrentExecutionInput, input), Context.add(CurrentCheckpoint, checkpoint), Context.add(InngestConfig, config), Context.add(HandlerFiberScope, handlerFiberScope));
|
|
24
|
-
function run$1(id, effect
|
|
25
|
-
if (Predicate.isNotUndefined(options)) return run({
|
|
26
|
-
input,
|
|
27
|
-
id: identity.reserve(id),
|
|
28
|
-
effect,
|
|
29
|
-
options
|
|
30
|
-
}).pipe(Effect.provide(runtime));
|
|
24
|
+
function run$1(id, effect) {
|
|
31
25
|
return run({
|
|
32
26
|
input,
|
|
33
27
|
id: identity.reserve(id),
|
|
@@ -4,7 +4,6 @@ import { StepError } from "../../errors.js";
|
|
|
4
4
|
import { InvokeFunction } from "../../domain/StepCommand.js";
|
|
5
5
|
import { StepCommandBus } from "../StepCommandBus.js";
|
|
6
6
|
import { StepIdentity } from "../StepIdentity.js";
|
|
7
|
-
import { decodeMemo } from "../../codec/StepResult.js";
|
|
8
7
|
import { Duration, Effect, Match, Predicate, Schema } from "effect";
|
|
9
8
|
//#region src/internal/runtime/steps/InvokeStep.ts
|
|
10
9
|
const invoke = (args) => Effect.gen(function* () {
|
|
@@ -13,7 +12,7 @@ const invoke = (args) => Effect.gen(function* () {
|
|
|
13
12
|
const bus = yield* StepCommandBus;
|
|
14
13
|
const info = yield* identity.resolve(args.id);
|
|
15
14
|
const memo = args.input.memoForStep(info);
|
|
16
|
-
return yield* Match.value(memo).pipe(Match.tag("MemoData", ({ data }) =>
|
|
15
|
+
return yield* Match.value(memo).pipe(Match.tag("MemoData", ({ data }) => Effect.succeed(data)), Match.tag("MemoError", ({ error }) => Effect.fail(StepError.make({
|
|
17
16
|
stepId: info.id,
|
|
18
17
|
message: Predicate.hasProperty(error, "message") ? String(error.message) : "Invoke failed",
|
|
19
18
|
cause: error
|