Created
October 24, 2024 15:35
-
-
Save igalshilman/6d807620048ca7aeb3c87f07e76f2297 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| * Copyright (c) 2023-2024 - Restate Software, Inc., Restate GmbH | |
| * | |
| * This file is part of the Restate SDK for Node.js/TypeScript, | |
| * which is released under the MIT license. | |
| * | |
| * You can find a copy of the license in file LICENSE in the root | |
| * directory of this repository or package, or at | |
| * https://github.com/restatedev/sdk-typescript/blob/main/LICENSE | |
| */ | |
| /* eslint-disable @typescript-eslint/no-unused-vars */ | |
| import * as restate from "@restatedev/restate-sdk"; | |
| import { CombineablePromise } from "@restatedev/restate-sdk"; | |
| interface PaymentRequest { | |
| amount: number; | |
| account: string; | |
| } | |
| interface PaymentSuccess { | |
| account: string; | |
| } | |
| const payment = restate.workflow({ | |
| name: "payment", | |
| handlers: { | |
| // these are the steps of the workflow, broken down to individual handlers | |
| // instead of a single monolithic function. | |
| makePayment: async ( | |
| ctx: restate.WorkflowSharedContext, | |
| payment: PaymentRequest | |
| ) => { | |
| // | |
| // For example use the stripe client to make the payment. | |
| // <!> Restate will store the result of this block durably, and | |
| // will make sure that it will not be executed again, once durably committed by restate. | |
| }, | |
| notifyUser: async ( | |
| ctx: restate.WorkflowSharedContext, | |
| payment: PaymentRequest | |
| ) => { | |
| // | |
| // use an email delivery service here to notify the user that their payment is being processed | |
| // | |
| }, | |
| emitEvent: async ( | |
| ctx: restate.WorkflowSharedContext, | |
| payment: PaymentRequest | |
| ) => { | |
| // | |
| // publish an event to an external system | |
| // | |
| }, | |
| /** | |
| * Run is the entry point for the workflow. | |
| * | |
| * @param ctx the restate context allows interacting with the restate APIs. | |
| * @param payment the argument | |
| * @returns | |
| */ | |
| run: async (ctx: restate.WorkflowContext, request: PaymentRequest) => { | |
| // | |
| // let's start by validating the workflow input. | |
| // The input might come directly from restate's ingress or via | |
| // a typed workflow client (see workflow_client.ts example) | |
| // | |
| if (request.amount < 0) { | |
| // this will stop the workflow | |
| throw new restate.TerminalError("Amount must be positive"); | |
| } | |
| const isCanceled = ctx.promise("canceled").get(); | |
| // step 1 | |
| const makePayment = ctx | |
| .workflowClient(payment, ctx.key) | |
| .makePayment(request); | |
| await CombineablePromise.race([isCanceled, makePayment]); | |
| // step 2 | |
| const notifyUser = ctx | |
| .workflowClient(payment, ctx.key) | |
| .notifyUser(request); | |
| await CombineablePromise.race([isCanceled, notifyUser]); | |
| // step 3 | |
| const emitEvent = ctx.workflowClient(payment, ctx.key).emitEvent(request); | |
| await CombineablePromise.race([isCanceled, emitEvent]); | |
| return "success"; | |
| }, | |
| /** | |
| * PaymentWebhook handler - is triggered directly as a Webhook by our imaginary payment provider. | |
| */ | |
| cancel: async (ctx: restate.WorkflowSharedContext) => { | |
| await ctx.promise("canceled").reject("cancelled"); | |
| }, | |
| }, | |
| }); | |
| export type PaymentWorkflow = typeof payment; | |
| restate.endpoint().bind(payment).listen(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment