| 261 | * @category Constructors |
| 262 | */ |
| 263 | export const make = < |
| 264 | const Name extends string, |
| 265 | Payload extends Schema.Struct.Fields | AnyStructSchema, |
| 266 | Success extends Schema.Schema.Any = typeof Schema.Void, |
| 267 | Error extends Schema.Schema.All = typeof Schema.Never |
| 268 | >( |
| 269 | options: { |
| 270 | readonly name: Name |
| 271 | readonly payload: Payload |
| 272 | readonly idempotencyKey: ( |
| 273 | payload: Payload extends Schema.Struct.Fields ? Schema.Struct.Type<Payload> : Payload["Type"] |
| 274 | ) => string |
| 275 | readonly success?: Success |
| 276 | readonly error?: Error |
| 277 | readonly suspendedRetrySchedule?: Schedule.Schedule<any, unknown> | undefined |
| 278 | readonly annotations?: Context.Context<never> |
| 279 | } |
| 280 | ): Workflow<Name, Payload extends Schema.Struct.Fields ? Schema.Struct<Payload> : Payload, Success, Error> => { |
| 281 | const makeExecutionId = (payload: any) => makeHashDigest(`${options.name}-${options.idempotencyKey(payload)}`) |
| 282 | const self: Workflow<Name, any, Success, Error> = { |
| 283 | [TypeId]: TypeId, |
| 284 | name: options.name, |
| 285 | payloadSchema: Schema.isSchema(options.payload) ? options.payload : Schema.Struct(options.payload as any), |
| 286 | successSchema: options.success ?? Schema.Void as any, |
| 287 | errorSchema: options.error ?? Schema.Never as any, |
| 288 | annotations: options.annotations ?? Context.empty(), |
| 289 | annotate(tag, value) { |
| 290 | return make({ |
| 291 | ...options, |
| 292 | annotations: Context.add(self.annotations, tag, value) |
| 293 | }) |
| 294 | }, |
| 295 | annotateContext(context) { |
| 296 | return make({ |
| 297 | ...options, |
| 298 | annotations: Context.merge(self.annotations, context) |
| 299 | }) |
| 300 | }, |
| 301 | execute: Effect.fnUntraced( |
| 302 | function*(fields: any, opts) { |
| 303 | const payload = self.payloadSchema.make(fields) |
| 304 | const engine = yield* EngineTag |
| 305 | const executionId = yield* makeExecutionId(payload) |
| 306 | yield* Effect.annotateCurrentSpan({ executionId }) |
| 307 | return yield* engine.execute(self, { |
| 308 | executionId, |
| 309 | payload, |
| 310 | discard: opts?.discard, |
| 311 | suspendedRetrySchedule: options.suspendedRetrySchedule |
| 312 | }) |
| 313 | }, |
| 314 | Effect.withSpan(`${options.name}.execute`, { captureStackTrace: false }) |
| 315 | ), |
| 316 | poll: Effect.fnUntraced( |
| 317 | function*(executionId: string) { |
| 318 | const engine = yield* EngineTag |
| 319 | return yield* engine.poll(self, executionId) |
| 320 | }, |