@effect/workflow 0.1.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/Activity/package.json +6 -0
- package/DurableClock/package.json +6 -0
- package/DurableDeferred/package.json +6 -0
- package/LICENSE +21 -0
- package/README.md +133 -0
- package/Workflow/package.json +6 -0
- package/WorkflowEngine/package.json +6 -0
- package/dist/cjs/Activity.js +100 -0
- package/dist/cjs/Activity.js.map +1 -0
- package/dist/cjs/DurableClock.js +49 -0
- package/dist/cjs/DurableClock.js.map +1 -0
- package/dist/cjs/DurableDeferred.js +158 -0
- package/dist/cjs/DurableDeferred.js.map +1 -0
- package/dist/cjs/Workflow.js +198 -0
- package/dist/cjs/Workflow.js.map +1 -0
- package/dist/cjs/WorkflowEngine.js +25 -0
- package/dist/cjs/WorkflowEngine.js.map +1 -0
- package/dist/cjs/index.js +18 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/internal/crypto.js +19 -0
- package/dist/cjs/internal/crypto.js.map +1 -0
- package/dist/dts/Activity.d.ts +70 -0
- package/dist/dts/Activity.d.ts.map +1 -0
- package/dist/dts/DurableClock.d.ts +42 -0
- package/dist/dts/DurableClock.d.ts.map +1 -0
- package/dist/dts/DurableDeferred.d.ts +252 -0
- package/dist/dts/DurableDeferred.d.ts.map +1 -0
- package/dist/dts/Workflow.d.ts +211 -0
- package/dist/dts/Workflow.d.ts.map +1 -0
- package/dist/dts/WorkflowEngine.d.ts +91 -0
- package/dist/dts/WorkflowEngine.d.ts.map +1 -0
- package/dist/dts/index.d.ts +21 -0
- package/dist/dts/index.d.ts.map +1 -0
- package/dist/dts/internal/crypto.d.ts +2 -0
- package/dist/dts/internal/crypto.d.ts.map +1 -0
- package/dist/esm/Activity.js +90 -0
- package/dist/esm/Activity.js.map +1 -0
- package/dist/esm/DurableClock.js +40 -0
- package/dist/esm/DurableClock.js.map +1 -0
- package/dist/esm/DurableDeferred.js +155 -0
- package/dist/esm/DurableDeferred.js.map +1 -0
- package/dist/esm/Workflow.js +183 -0
- package/dist/esm/Workflow.js.map +1 -0
- package/dist/esm/WorkflowEngine.js +15 -0
- package/dist/esm/WorkflowEngine.js.map +1 -0
- package/dist/esm/index.js +21 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/internal/crypto.js +11 -0
- package/dist/esm/internal/crypto.js.map +1 -0
- package/dist/esm/package.json +4 -0
- package/package.json +74 -0
- package/src/Activity.ts +177 -0
- package/src/DurableClock.ts +82 -0
- package/src/DurableDeferred.ts +461 -0
- package/src/Workflow.ts +401 -0
- package/src/WorkflowEngine.ts +122 -0
- package/src/index.ts +24 -0
- package/src/internal/crypto.ts +15 -0
package/src/Activity.ts
ADDED
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @since 1.0.0
|
|
3
|
+
*/
|
|
4
|
+
import * as Context from "effect/Context"
|
|
5
|
+
import * as Effect from "effect/Effect"
|
|
6
|
+
import * as Effectable from "effect/Effectable"
|
|
7
|
+
import type * as Exit from "effect/Exit"
|
|
8
|
+
import { dual } from "effect/Function"
|
|
9
|
+
import * as Schema from "effect/Schema"
|
|
10
|
+
import { makeHashDigest } from "./internal/crypto.js"
|
|
11
|
+
import type { WorkflowEngine, WorkflowInstance } from "./WorkflowEngine.js"
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @since 1.0.0
|
|
15
|
+
* @category Symbols
|
|
16
|
+
*/
|
|
17
|
+
export const TypeId: unique symbol = Symbol.for("@effect/workflow/Activity")
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @since 1.0.0
|
|
21
|
+
* @category Symbols
|
|
22
|
+
*/
|
|
23
|
+
export type TypeId = typeof TypeId
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @since 1.0.0
|
|
27
|
+
* @category Models
|
|
28
|
+
*/
|
|
29
|
+
export interface Activity<
|
|
30
|
+
Success extends Schema.Schema.Any,
|
|
31
|
+
Error extends Schema.Schema.All,
|
|
32
|
+
R
|
|
33
|
+
> extends
|
|
34
|
+
Effect.Effect<
|
|
35
|
+
Success["Type"],
|
|
36
|
+
Error["Type"],
|
|
37
|
+
Success["Context"] | Error["Context"] | R | WorkflowEngine | WorkflowInstance
|
|
38
|
+
>
|
|
39
|
+
{
|
|
40
|
+
readonly [TypeId]: TypeId
|
|
41
|
+
readonly name: string
|
|
42
|
+
readonly successSchema: Success
|
|
43
|
+
readonly errorSchema: Error
|
|
44
|
+
readonly exitSchema: Schema.Schema<
|
|
45
|
+
Exit.Exit<Success["Type"], Error["Type"]>,
|
|
46
|
+
Exit.Exit<Success["Encoded"], Error["Encoded"]>,
|
|
47
|
+
Success["Context"] | Error["Context"]
|
|
48
|
+
>
|
|
49
|
+
readonly executeEncoded: Effect.Effect<
|
|
50
|
+
Success["Encoded"],
|
|
51
|
+
Error["Encoded"],
|
|
52
|
+
Success["Context"] | Error["Context"] | R | WorkflowEngine | WorkflowInstance
|
|
53
|
+
>
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* @since 1.0.0
|
|
58
|
+
* @category Models
|
|
59
|
+
*/
|
|
60
|
+
export interface Any {
|
|
61
|
+
readonly [TypeId]: TypeId
|
|
62
|
+
readonly name: string
|
|
63
|
+
readonly successSchema: Schema.Schema.Any
|
|
64
|
+
readonly errorSchema: Schema.Schema.All
|
|
65
|
+
readonly executeEncoded: Effect.Effect<any, any, any>
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* @since 1.0.0
|
|
70
|
+
* @category Constructors
|
|
71
|
+
*/
|
|
72
|
+
export const make = <
|
|
73
|
+
R,
|
|
74
|
+
Success extends Schema.Schema.Any = typeof Schema.Void,
|
|
75
|
+
Error extends Schema.Schema.All = typeof Schema.Never
|
|
76
|
+
>(options: {
|
|
77
|
+
readonly name: string
|
|
78
|
+
readonly success?: Success
|
|
79
|
+
readonly error?: Error
|
|
80
|
+
readonly execute: Effect.Effect<Success["Type"], Error["Type"], R>
|
|
81
|
+
}): Activity<Success, Error, Exclude<R, WorkflowInstance | WorkflowEngine>> => {
|
|
82
|
+
const successSchema = options.success ?? Schema.Void as any as Success
|
|
83
|
+
const errorSchema = options.error ?? Schema.Never as any as Error
|
|
84
|
+
// eslint-disable-next-line prefer-const
|
|
85
|
+
let execute!: Effect.Effect<Success["Type"], Error["Type"], any>
|
|
86
|
+
const self: Activity<Success, Error, Exclude<R, WorkflowInstance | WorkflowEngine>> = {
|
|
87
|
+
...Effectable.CommitPrototype,
|
|
88
|
+
[TypeId]: TypeId,
|
|
89
|
+
name: options.name,
|
|
90
|
+
successSchema,
|
|
91
|
+
errorSchema,
|
|
92
|
+
exitSchema: Schema.ExitFromSelf({
|
|
93
|
+
success: successSchema,
|
|
94
|
+
failure: errorSchema,
|
|
95
|
+
defect: Schema.Defect
|
|
96
|
+
}),
|
|
97
|
+
executeEncoded: Effect.matchEffect(options.execute, {
|
|
98
|
+
onFailure: (error) => Effect.flatMap(Effect.orDie(Schema.encode(self.errorSchema as any)(error)), Effect.fail),
|
|
99
|
+
onSuccess: (value) => Effect.orDie(Schema.encode(self.successSchema)(value))
|
|
100
|
+
}),
|
|
101
|
+
commit() {
|
|
102
|
+
return execute
|
|
103
|
+
}
|
|
104
|
+
} as any
|
|
105
|
+
execute = makeExecute(self)
|
|
106
|
+
return self
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* @since 1.0.0
|
|
111
|
+
* @category Error handling
|
|
112
|
+
*/
|
|
113
|
+
export const retry: typeof Effect.retry = dual(
|
|
114
|
+
2,
|
|
115
|
+
(effect: Effect.Effect<any, any, any>, options: {}) =>
|
|
116
|
+
Effect.suspend(() => {
|
|
117
|
+
let attempt = 1
|
|
118
|
+
return Effect.suspend(() => Effect.provideService(effect, CurrentAttempt, attempt++)).pipe(
|
|
119
|
+
Effect.retry(options)
|
|
120
|
+
)
|
|
121
|
+
})
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* @since 1.0.0
|
|
126
|
+
* @category Attempts
|
|
127
|
+
*/
|
|
128
|
+
export class CurrentAttempt extends Context.Reference<CurrentAttempt>()("@effect/workflow/Activity/CurrentAttempt", {
|
|
129
|
+
defaultValue: () => 0
|
|
130
|
+
}) {}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* @since 1.0.0
|
|
134
|
+
* @category Execution ID
|
|
135
|
+
*/
|
|
136
|
+
export const executionIdWithAttempt: Effect.Effect<
|
|
137
|
+
string,
|
|
138
|
+
never,
|
|
139
|
+
WorkflowInstance
|
|
140
|
+
> = Effect.gen(function*() {
|
|
141
|
+
const instance = yield* InstanceTag
|
|
142
|
+
const attempt = yield* CurrentAttempt
|
|
143
|
+
return yield* makeHashDigest(`${instance.executionId}-${attempt}`)
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
// -----------------------------------------------------------------------------
|
|
147
|
+
// internal
|
|
148
|
+
// -----------------------------------------------------------------------------
|
|
149
|
+
|
|
150
|
+
const EngineTag = Context.GenericTag<WorkflowEngine, WorkflowEngine["Type"]>(
|
|
151
|
+
"@effect/workflow/WorkflowEngine" satisfies typeof WorkflowEngine.key
|
|
152
|
+
)
|
|
153
|
+
const InstanceTag = Context.GenericTag<WorkflowInstance, WorkflowInstance["Type"]>(
|
|
154
|
+
"@effect/workflow/WorkflowEngine/WorkflowInstance" satisfies typeof WorkflowInstance.key
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
const makeExecute = Effect.fnUntraced(function*<
|
|
158
|
+
R,
|
|
159
|
+
Success extends Schema.Schema.Any = typeof Schema.Void,
|
|
160
|
+
Error extends Schema.Schema.All = typeof Schema.Never
|
|
161
|
+
>(activity: Activity<Success, Error, R>) {
|
|
162
|
+
const engine = yield* EngineTag
|
|
163
|
+
const instance = yield* InstanceTag
|
|
164
|
+
const attempt = yield* CurrentAttempt
|
|
165
|
+
const result = yield* engine.activityExecute({
|
|
166
|
+
activity,
|
|
167
|
+
attempt
|
|
168
|
+
})
|
|
169
|
+
if (result._tag === "Suspended") {
|
|
170
|
+
instance.suspended = true
|
|
171
|
+
return yield* Effect.interrupt
|
|
172
|
+
}
|
|
173
|
+
const exit = yield* Effect.orDie(
|
|
174
|
+
Schema.decode(activity.exitSchema)(result.exit)
|
|
175
|
+
)
|
|
176
|
+
return yield* exit
|
|
177
|
+
})
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @since 1.0.0
|
|
3
|
+
*/
|
|
4
|
+
import * as Context from "effect/Context"
|
|
5
|
+
import * as Duration from "effect/Duration"
|
|
6
|
+
import * as Effect from "effect/Effect"
|
|
7
|
+
import type * as Schema from "effect/Schema"
|
|
8
|
+
import * as DurableDeferred from "./DurableDeferred.js"
|
|
9
|
+
import type { WorkflowEngine, WorkflowInstance } from "./WorkflowEngine.js"
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @since 1.0.0
|
|
13
|
+
* @category Symbols
|
|
14
|
+
*/
|
|
15
|
+
export const TypeId: unique symbol = Symbol.for("@effect/workflow/DurableClock")
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @since 1.0.0
|
|
19
|
+
* @category Symbols
|
|
20
|
+
*/
|
|
21
|
+
export type TypeId = typeof TypeId
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @since 1.0.0
|
|
25
|
+
* @category Models
|
|
26
|
+
*/
|
|
27
|
+
export interface DurableClock {
|
|
28
|
+
readonly [TypeId]: TypeId
|
|
29
|
+
readonly name: string
|
|
30
|
+
readonly duration: Duration.Duration
|
|
31
|
+
readonly deferred: DurableDeferred.DurableDeferred<typeof Schema.Void>
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @since 1.0.0
|
|
36
|
+
* @category Constructors
|
|
37
|
+
*/
|
|
38
|
+
export const make = (options: {
|
|
39
|
+
readonly name: string
|
|
40
|
+
readonly duration: Duration.DurationInput
|
|
41
|
+
}): DurableClock => ({
|
|
42
|
+
[TypeId]: TypeId,
|
|
43
|
+
name: options.name,
|
|
44
|
+
duration: Duration.decode(options.duration),
|
|
45
|
+
deferred: DurableDeferred.make(`DurableClock/${options.name}`)
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
const EngineTag = Context.GenericTag<WorkflowEngine, WorkflowEngine["Type"]>(
|
|
49
|
+
"@effect/workflow/WorkflowEngine" satisfies typeof WorkflowEngine.key
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
const InstanceTag = Context.GenericTag<WorkflowInstance, WorkflowInstance["Type"]>(
|
|
53
|
+
"@effect/workflow/WorkflowEngine/WorkflowInstance" satisfies typeof WorkflowInstance.key
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* @since 1.0.0
|
|
58
|
+
* @category Sleeping
|
|
59
|
+
*/
|
|
60
|
+
export const sleep: (
|
|
61
|
+
options: {
|
|
62
|
+
readonly name: string
|
|
63
|
+
readonly duration: Duration.DurationInput
|
|
64
|
+
}
|
|
65
|
+
) => Effect.Effect<
|
|
66
|
+
void,
|
|
67
|
+
never,
|
|
68
|
+
WorkflowEngine | WorkflowInstance
|
|
69
|
+
> = Effect.fnUntraced(function*(options: {
|
|
70
|
+
readonly name: string
|
|
71
|
+
readonly duration: Duration.DurationInput
|
|
72
|
+
}) {
|
|
73
|
+
const engine = yield* EngineTag
|
|
74
|
+
const instance = yield* InstanceTag
|
|
75
|
+
const clock = make(options)
|
|
76
|
+
yield* engine.scheduleClock({
|
|
77
|
+
workflow: instance.workflow,
|
|
78
|
+
executionId: instance.executionId,
|
|
79
|
+
clock
|
|
80
|
+
})
|
|
81
|
+
return yield* DurableDeferred.await(clock.deferred)
|
|
82
|
+
})
|
|
@@ -0,0 +1,461 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @since 1.0.0
|
|
3
|
+
*/
|
|
4
|
+
import type * as Brand from "effect/Brand"
|
|
5
|
+
import type * as Cause from "effect/Cause"
|
|
6
|
+
import * as Context from "effect/Context"
|
|
7
|
+
import * as Effect from "effect/Effect"
|
|
8
|
+
import * as Encoding from "effect/Encoding"
|
|
9
|
+
import * as Exit from "effect/Exit"
|
|
10
|
+
import { dual } from "effect/Function"
|
|
11
|
+
import * as Option from "effect/Option"
|
|
12
|
+
import * as Schema from "effect/Schema"
|
|
13
|
+
import type * as Workflow from "./Workflow.js"
|
|
14
|
+
import type { WorkflowEngine, WorkflowInstance } from "./WorkflowEngine.js"
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @since 1.0.0
|
|
18
|
+
* @category Symbols
|
|
19
|
+
*/
|
|
20
|
+
export const TypeId: unique symbol = Symbol.for("@effect/workflow/DurableDeferred")
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @since 1.0.0
|
|
24
|
+
* @category Symbols
|
|
25
|
+
*/
|
|
26
|
+
export type TypeId = typeof TypeId
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* @since 1.0.0
|
|
30
|
+
* @category Models
|
|
31
|
+
*/
|
|
32
|
+
export interface DurableDeferred<
|
|
33
|
+
Success extends Schema.Schema.Any,
|
|
34
|
+
Error extends Schema.Schema.All = typeof Schema.Never
|
|
35
|
+
> {
|
|
36
|
+
readonly [TypeId]: TypeId
|
|
37
|
+
readonly name: string
|
|
38
|
+
readonly successSchema: Success
|
|
39
|
+
readonly errorSchema: Error
|
|
40
|
+
readonly exitSchema: Schema.Exit<Success, Error, typeof Schema.Defect>
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* @since 1.0.0
|
|
45
|
+
* @category Models
|
|
46
|
+
*/
|
|
47
|
+
export interface Any {
|
|
48
|
+
readonly [TypeId]: TypeId
|
|
49
|
+
readonly name: string
|
|
50
|
+
readonly successSchema: Schema.Schema.Any
|
|
51
|
+
readonly errorSchema: Schema.Schema.All
|
|
52
|
+
readonly exitSchema: Schema.Exit<any, any, any>
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* @since 1.0.0
|
|
57
|
+
* @category Constructors
|
|
58
|
+
*/
|
|
59
|
+
export const make = <
|
|
60
|
+
Success extends Schema.Schema.Any = typeof Schema.Void,
|
|
61
|
+
Error extends Schema.Schema.All = typeof Schema.Never
|
|
62
|
+
>(name: string, options?: {
|
|
63
|
+
readonly success?: Success
|
|
64
|
+
readonly error?: Error
|
|
65
|
+
}): DurableDeferred<Success, Error> => ({
|
|
66
|
+
[TypeId]: TypeId,
|
|
67
|
+
name,
|
|
68
|
+
successSchema: options?.success ?? Schema.Void as any,
|
|
69
|
+
errorSchema: options?.error ?? Schema.Never as any,
|
|
70
|
+
exitSchema: Schema.Exit({
|
|
71
|
+
success: options?.success ?? Schema.Void as any,
|
|
72
|
+
failure: options?.error ?? Schema.Never as any,
|
|
73
|
+
defect: Schema.Defect
|
|
74
|
+
})
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
const EngineTag = Context.GenericTag<WorkflowEngine, WorkflowEngine["Type"]>(
|
|
78
|
+
"@effect/workflow/WorkflowEngine" satisfies typeof WorkflowEngine.key
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
const InstanceTag = Context.GenericTag<WorkflowInstance, WorkflowInstance["Type"]>(
|
|
82
|
+
"@effect/workflow/WorkflowEngine/WorkflowInstance" satisfies typeof WorkflowInstance.key
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
const await_: <Success extends Schema.Schema.Any, Error extends Schema.Schema.All>(
|
|
86
|
+
self: DurableDeferred<Success, Error>
|
|
87
|
+
) => Effect.Effect<
|
|
88
|
+
Success["Type"],
|
|
89
|
+
Error["Type"],
|
|
90
|
+
WorkflowEngine | WorkflowInstance | Success["Context"] | Error["Context"]
|
|
91
|
+
> = Effect.fnUntraced(function*<
|
|
92
|
+
Success extends Schema.Schema.Any,
|
|
93
|
+
Error extends Schema.Schema.All
|
|
94
|
+
>(self: DurableDeferred<Success, Error>) {
|
|
95
|
+
const engine = yield* EngineTag
|
|
96
|
+
const instance = yield* InstanceTag
|
|
97
|
+
const oexit = yield* engine.deferredResult(self)
|
|
98
|
+
if (Option.isNone(oexit)) {
|
|
99
|
+
instance.suspended = true
|
|
100
|
+
return yield* Effect.interrupt
|
|
101
|
+
}
|
|
102
|
+
return yield* Effect.flatten(Effect.orDie(
|
|
103
|
+
Schema.decodeUnknown(self.exitSchema)(oexit.value)
|
|
104
|
+
))
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
export {
|
|
108
|
+
/**
|
|
109
|
+
* @since 1.0.0
|
|
110
|
+
* @category Combinators
|
|
111
|
+
*/
|
|
112
|
+
await_ as await
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* @since 1.0.0
|
|
117
|
+
* @category Token
|
|
118
|
+
*/
|
|
119
|
+
export const TokenTypeId: unique symbol = Symbol.for("@effect/workflow/DurableDeferred/Token")
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* @since 1.0.0
|
|
123
|
+
* @category Token
|
|
124
|
+
*/
|
|
125
|
+
export type TokenTypeId = typeof TokenTypeId
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* @since 1.0.0
|
|
129
|
+
* @category Token
|
|
130
|
+
*/
|
|
131
|
+
export type Token = Brand.Branded<string, TokenTypeId>
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* @since 1.0.0
|
|
135
|
+
* @category Token
|
|
136
|
+
*/
|
|
137
|
+
export const Token: Schema.brand<
|
|
138
|
+
typeof Schema.String,
|
|
139
|
+
typeof TokenTypeId
|
|
140
|
+
> = Schema.String.pipe(
|
|
141
|
+
Schema.brand(TokenTypeId)
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* @since 1.0.0
|
|
146
|
+
* @category Token
|
|
147
|
+
*/
|
|
148
|
+
export class TokenParsed extends Schema.Class<TokenParsed>("@effect/workflow/DurableDeferred/TokenParsed")({
|
|
149
|
+
workflowName: Schema.String,
|
|
150
|
+
executionId: Schema.String,
|
|
151
|
+
deferredName: Schema.String
|
|
152
|
+
}) {
|
|
153
|
+
/**
|
|
154
|
+
* @since 1.0.0
|
|
155
|
+
*/
|
|
156
|
+
get asToken(): Token {
|
|
157
|
+
return Encoding.encodeBase64Url(JSON.stringify([this.workflowName, this.executionId, this.deferredName])) as Token
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* @since 1.0.0
|
|
162
|
+
*/
|
|
163
|
+
static readonly FromString: Schema.Schema<
|
|
164
|
+
TokenParsed,
|
|
165
|
+
string
|
|
166
|
+
> = Schema.StringFromBase64Url.pipe(
|
|
167
|
+
Schema.compose(Schema.parseJson(Schema.Tuple(Schema.String, Schema.String, Schema.String))),
|
|
168
|
+
Schema.transform(TokenParsed, {
|
|
169
|
+
decode: ([workflowName, executionId, deferredName]) =>
|
|
170
|
+
new TokenParsed({
|
|
171
|
+
workflowName,
|
|
172
|
+
executionId,
|
|
173
|
+
deferredName
|
|
174
|
+
}),
|
|
175
|
+
encode: (parsed) => [parsed.workflowName, parsed.executionId, parsed.deferredName] as const
|
|
176
|
+
})
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* @since 1.0.0
|
|
181
|
+
*/
|
|
182
|
+
static readonly fromString = Schema.decodeSync(TokenParsed.FromString)
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* @since 1.0.0
|
|
186
|
+
*/
|
|
187
|
+
static readonly encode = Schema.encodeSync(TokenParsed.FromString)
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* @since 1.0.0
|
|
192
|
+
* @category Token
|
|
193
|
+
*/
|
|
194
|
+
export const token: <Success extends Schema.Schema.Any, Error extends Schema.Schema.All>(
|
|
195
|
+
self: DurableDeferred<Success, Error>
|
|
196
|
+
) => Effect.Effect<Token, never, WorkflowInstance> = Effect.fnUntraced(function*<
|
|
197
|
+
Success extends Schema.Schema.Any,
|
|
198
|
+
Error extends Schema.Schema.All
|
|
199
|
+
>(self: DurableDeferred<Success, Error>) {
|
|
200
|
+
const instance = yield* InstanceTag
|
|
201
|
+
return tokenFromExecutionId(self, instance)
|
|
202
|
+
})
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* @since 1.0.0
|
|
206
|
+
* @category Token
|
|
207
|
+
*/
|
|
208
|
+
export const tokenFromExecutionId: {
|
|
209
|
+
/**
|
|
210
|
+
* @since 1.0.0
|
|
211
|
+
* @category Token
|
|
212
|
+
*/
|
|
213
|
+
(
|
|
214
|
+
options: {
|
|
215
|
+
readonly workflow: Workflow.Any
|
|
216
|
+
readonly executionId: string
|
|
217
|
+
}
|
|
218
|
+
): <Success extends Schema.Schema.Any, Error extends Schema.Schema.All>(
|
|
219
|
+
self: DurableDeferred<Success, Error>
|
|
220
|
+
) => Token
|
|
221
|
+
/**
|
|
222
|
+
* @since 1.0.0
|
|
223
|
+
* @category Token
|
|
224
|
+
*/
|
|
225
|
+
<Success extends Schema.Schema.Any, Error extends Schema.Schema.All>(
|
|
226
|
+
self: DurableDeferred<Success, Error>,
|
|
227
|
+
options: { readonly workflow: Workflow.Any; readonly executionId: string }
|
|
228
|
+
): Token
|
|
229
|
+
} = dual(
|
|
230
|
+
2,
|
|
231
|
+
<Success extends Schema.Schema.Any, Error extends Schema.Schema.All>(
|
|
232
|
+
self: DurableDeferred<Success, Error>,
|
|
233
|
+
options: {
|
|
234
|
+
readonly workflow: Workflow.Any
|
|
235
|
+
readonly executionId: string
|
|
236
|
+
}
|
|
237
|
+
): Token =>
|
|
238
|
+
new TokenParsed({
|
|
239
|
+
workflowName: options.workflow.name,
|
|
240
|
+
executionId: options.executionId,
|
|
241
|
+
deferredName: self.name
|
|
242
|
+
}).asToken
|
|
243
|
+
)
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* @since 1.0.0
|
|
247
|
+
* @category Token
|
|
248
|
+
*/
|
|
249
|
+
export const tokenFromPayload: {
|
|
250
|
+
/**
|
|
251
|
+
* @since 1.0.0
|
|
252
|
+
* @category Token
|
|
253
|
+
*/
|
|
254
|
+
<W extends Workflow.Any>(
|
|
255
|
+
options: {
|
|
256
|
+
readonly workflow: W
|
|
257
|
+
readonly payload: Schema.Simplify<Schema.Struct.Constructor<W["payloadSchema"]["fields"]>>
|
|
258
|
+
}
|
|
259
|
+
): <Success extends Schema.Schema.Any, Error extends Schema.Schema.All>(
|
|
260
|
+
self: DurableDeferred<Success, Error>
|
|
261
|
+
) => Effect.Effect<Token>
|
|
262
|
+
/**
|
|
263
|
+
* @since 1.0.0
|
|
264
|
+
* @category Token
|
|
265
|
+
*/
|
|
266
|
+
<Success extends Schema.Schema.Any, Error extends Schema.Schema.All, W extends Workflow.Any>(
|
|
267
|
+
self: DurableDeferred<Success, Error>,
|
|
268
|
+
options: {
|
|
269
|
+
readonly workflow: W
|
|
270
|
+
readonly payload: Schema.Simplify<Schema.Struct.Constructor<W["payloadSchema"]["fields"]>>
|
|
271
|
+
}
|
|
272
|
+
): Effect.Effect<Token>
|
|
273
|
+
} = dual(
|
|
274
|
+
2,
|
|
275
|
+
<Success extends Schema.Schema.Any, Error extends Schema.Schema.All, W extends Workflow.Any>(
|
|
276
|
+
self: DurableDeferred<Success, Error>,
|
|
277
|
+
options: {
|
|
278
|
+
readonly workflow: W
|
|
279
|
+
readonly payload: Schema.Simplify<Schema.Struct.Constructor<W["payloadSchema"]["fields"]>>
|
|
280
|
+
}
|
|
281
|
+
): Effect.Effect<Token> =>
|
|
282
|
+
Effect.map(options.workflow.executionId(options.payload), (executionId) =>
|
|
283
|
+
tokenFromExecutionId(self, {
|
|
284
|
+
workflow: options.workflow,
|
|
285
|
+
executionId
|
|
286
|
+
}))
|
|
287
|
+
)
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* @since 1.0.0
|
|
291
|
+
* @category Combinators
|
|
292
|
+
*/
|
|
293
|
+
export const done: {
|
|
294
|
+
/**
|
|
295
|
+
* @since 1.0.0
|
|
296
|
+
* @category Combinators
|
|
297
|
+
*/
|
|
298
|
+
<Success extends Schema.Schema.Any, Error extends Schema.Schema.All>(
|
|
299
|
+
options: {
|
|
300
|
+
readonly token: Token
|
|
301
|
+
readonly exit: Exit.Exit<Success["Type"], Error["Type"]>
|
|
302
|
+
}
|
|
303
|
+
): (self: DurableDeferred<Success, Error>) => Effect.Effect<
|
|
304
|
+
void,
|
|
305
|
+
never,
|
|
306
|
+
WorkflowEngine | Success["Context"] | Error["Context"]
|
|
307
|
+
>
|
|
308
|
+
/**
|
|
309
|
+
* @since 1.0.0
|
|
310
|
+
* @category Combinators
|
|
311
|
+
*/
|
|
312
|
+
<Success extends Schema.Schema.Any, Error extends Schema.Schema.All>(
|
|
313
|
+
self: DurableDeferred<Success, Error>,
|
|
314
|
+
options: {
|
|
315
|
+
readonly token: Token
|
|
316
|
+
readonly exit: Exit.Exit<Success["Type"], Error["Type"]>
|
|
317
|
+
}
|
|
318
|
+
): Effect.Effect<void, never, WorkflowEngine | Success["Context"] | Error["Context"]>
|
|
319
|
+
} = dual(
|
|
320
|
+
2,
|
|
321
|
+
Effect.fnUntraced(function*<Success extends Schema.Schema.Any, Error extends Schema.Schema.All>(
|
|
322
|
+
self: DurableDeferred<Success, Error>,
|
|
323
|
+
options: {
|
|
324
|
+
readonly token: Token
|
|
325
|
+
readonly exit: Exit.Exit<Success["Type"], Error["Type"]>
|
|
326
|
+
}
|
|
327
|
+
) {
|
|
328
|
+
const engine = yield* EngineTag
|
|
329
|
+
const token = TokenParsed.fromString(options.token)
|
|
330
|
+
const exit = yield* Schema.encode(self.exitSchema)(options.exit)
|
|
331
|
+
yield* engine.deferredDone({
|
|
332
|
+
workflowName: token.workflowName,
|
|
333
|
+
executionId: token.executionId,
|
|
334
|
+
deferred: self,
|
|
335
|
+
exit: exit as any
|
|
336
|
+
})
|
|
337
|
+
}, Effect.orDie)
|
|
338
|
+
)
|
|
339
|
+
|
|
340
|
+
/**
|
|
341
|
+
* @since 1.0.0
|
|
342
|
+
* @category Combinators
|
|
343
|
+
*/
|
|
344
|
+
export const succeed: {
|
|
345
|
+
/**
|
|
346
|
+
* @since 1.0.0
|
|
347
|
+
* @category Combinators
|
|
348
|
+
*/
|
|
349
|
+
<Success extends Schema.Schema.Any, Error extends Schema.Schema.All>(
|
|
350
|
+
options: {
|
|
351
|
+
readonly token: Token
|
|
352
|
+
readonly value: Success["Type"]
|
|
353
|
+
}
|
|
354
|
+
): (self: DurableDeferred<Success, Error>) => Effect.Effect<void, never, WorkflowEngine | Success["Context"]>
|
|
355
|
+
/**
|
|
356
|
+
* @since 1.0.0
|
|
357
|
+
* @category Combinators
|
|
358
|
+
*/
|
|
359
|
+
<Success extends Schema.Schema.Any, Error extends Schema.Schema.All>(
|
|
360
|
+
self: DurableDeferred<Success, Error>,
|
|
361
|
+
options: {
|
|
362
|
+
readonly token: Token
|
|
363
|
+
readonly value: Success["Type"]
|
|
364
|
+
}
|
|
365
|
+
): Effect.Effect<void, never, WorkflowEngine | Success["Context"]>
|
|
366
|
+
} = dual(
|
|
367
|
+
2,
|
|
368
|
+
<Success extends Schema.Schema.Any, Error extends Schema.Schema.All>(
|
|
369
|
+
self: DurableDeferred<Success, Error>,
|
|
370
|
+
options: {
|
|
371
|
+
readonly token: Token
|
|
372
|
+
readonly value: Success["Type"]
|
|
373
|
+
}
|
|
374
|
+
): Effect.Effect<void, never, WorkflowEngine | Success["Context"]> =>
|
|
375
|
+
done(self, {
|
|
376
|
+
token: options.token,
|
|
377
|
+
exit: Exit.succeed(options.value)
|
|
378
|
+
})
|
|
379
|
+
)
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* @since 1.0.0
|
|
383
|
+
* @category Combinators
|
|
384
|
+
*/
|
|
385
|
+
export const fail: {
|
|
386
|
+
/**
|
|
387
|
+
* @since 1.0.0
|
|
388
|
+
* @category Combinators
|
|
389
|
+
*/
|
|
390
|
+
<Success extends Schema.Schema.Any, Error extends Schema.Schema.All>(
|
|
391
|
+
options: {
|
|
392
|
+
readonly token: Token
|
|
393
|
+
readonly error: Error["Type"]
|
|
394
|
+
}
|
|
395
|
+
): (self: DurableDeferred<Success, Error>) => Effect.Effect<void, never, WorkflowEngine | Error["Context"]>
|
|
396
|
+
/**
|
|
397
|
+
* @since 1.0.0
|
|
398
|
+
* @category Combinators
|
|
399
|
+
*/
|
|
400
|
+
<Success extends Schema.Schema.Any, Error extends Schema.Schema.All>(
|
|
401
|
+
self: DurableDeferred<Success, Error>,
|
|
402
|
+
options: {
|
|
403
|
+
readonly token: Token
|
|
404
|
+
readonly error: Error["Type"]
|
|
405
|
+
}
|
|
406
|
+
): Effect.Effect<void, never, WorkflowEngine | Error["Context"]>
|
|
407
|
+
} = dual(
|
|
408
|
+
2,
|
|
409
|
+
<Success extends Schema.Schema.Any, Error extends Schema.Schema.All>(
|
|
410
|
+
self: DurableDeferred<Success, Error>,
|
|
411
|
+
options: {
|
|
412
|
+
readonly token: Token
|
|
413
|
+
readonly error: Error["Type"]
|
|
414
|
+
}
|
|
415
|
+
): Effect.Effect<void, never, WorkflowEngine | Error["Context"]> =>
|
|
416
|
+
done(self, {
|
|
417
|
+
token: options.token,
|
|
418
|
+
exit: Exit.fail(options.error)
|
|
419
|
+
})
|
|
420
|
+
)
|
|
421
|
+
|
|
422
|
+
/**
|
|
423
|
+
* @since 1.0.0
|
|
424
|
+
* @category Combinators
|
|
425
|
+
*/
|
|
426
|
+
export const failCause: {
|
|
427
|
+
/**
|
|
428
|
+
* @since 1.0.0
|
|
429
|
+
* @category Combinators
|
|
430
|
+
*/
|
|
431
|
+
<Success extends Schema.Schema.Any, Error extends Schema.Schema.All>(
|
|
432
|
+
options: {
|
|
433
|
+
readonly token: Token
|
|
434
|
+
readonly cause: Cause.Cause<Error["Type"]>
|
|
435
|
+
}
|
|
436
|
+
): (self: DurableDeferred<Success, Error>) => Effect.Effect<void, never, WorkflowEngine | Error["Context"]>
|
|
437
|
+
/**
|
|
438
|
+
* @since 1.0.0
|
|
439
|
+
* @category Combinators
|
|
440
|
+
*/
|
|
441
|
+
<Success extends Schema.Schema.Any, Error extends Schema.Schema.All>(
|
|
442
|
+
self: DurableDeferred<Success, Error>,
|
|
443
|
+
options: {
|
|
444
|
+
readonly token: Token
|
|
445
|
+
readonly cause: Cause.Cause<Error["Type"]>
|
|
446
|
+
}
|
|
447
|
+
): Effect.Effect<void, never, WorkflowEngine | Error["Context"]>
|
|
448
|
+
} = dual(
|
|
449
|
+
2,
|
|
450
|
+
<Success extends Schema.Schema.Any, Error extends Schema.Schema.All>(
|
|
451
|
+
self: DurableDeferred<Success, Error>,
|
|
452
|
+
options: {
|
|
453
|
+
readonly token: Token
|
|
454
|
+
readonly cause: Cause.Cause<Error["Type"]>
|
|
455
|
+
}
|
|
456
|
+
): Effect.Effect<void, never, WorkflowEngine | Error["Context"]> =>
|
|
457
|
+
done(self, {
|
|
458
|
+
token: options.token,
|
|
459
|
+
exit: Exit.failCause(options.cause)
|
|
460
|
+
})
|
|
461
|
+
)
|