Created
April 14, 2025 09:40
-
-
Save slinkydeveloper/52ff6c0c12ba8bbc9ccf71253fad9910 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
import * as restate from "@restatedev/restate-sdk"; | |
import { v4 as uuid } from 'uuid'; | |
import {TerminalError} from "@restatedev/restate-sdk"; | |
type FlightRequest = { flightId: string, passengerName: string }; | |
type CarRequest = { pickupLocation: string, rentalDate: string }; | |
type PaymentRequest = { cardNumber: string, amount: number }; | |
type BookingRequest = { flight: FlightRequest, car: CarRequest, payment: PaymentRequest }; | |
const booking = restate.service({ | |
name: "Booking", | |
handlers: { | |
run: async (ctx: restate.Context, req: BookingRequest) => { | |
const {flight, car, payment} = req | |
const compensations = []; | |
try { | |
compensations.push(async () => await ctx.run("unreserve-flight", () => unreserveFlight(flight))) | |
const flightBookingId = await ctx.run("reserve-flight", () => reserveFlight(flight)) | |
compensations.push(async () => await ctx.run("unreserve-car", () => unreserveCar(car))) | |
const carBookingId = await ctx.run("reserve-car", () => reserveCar(car)) | |
const paymentId = await ctx.run("generate-payment-id", () => uuid()); | |
compensations.push(async () => ctx.run("refund-payment", () => refundPayment(paymentId))); | |
await ctx.run("do-payment", () => doPayment(paymentId, payment)); | |
await ctx.run("confirm-flight", () => confirmFlight(flightBookingId)) | |
await ctx.run("confirm-car", () => confirmCar(carBookingId)) | |
} catch (e) { | |
for (const compensation of compensations.reverse()) { | |
await compensation(); | |
} | |
} | |
} | |
}, | |
}); | |
restate.endpoint() | |
.bind(booking) | |
.listen(); | |
// ---- Mocks | |
async function reserveFlight(flight: FlightRequest): Promise<string> { | |
console.log(`Reserved flight ${flight.flightId} for passenger ${flight.passengerName}`) | |
return flight.flightId + "-" + flight.passengerName | |
} | |
async function confirmFlight(flightBookingId: string) { | |
console.log(`Confirm flight with booking id ${flightBookingId}`) | |
} | |
async function unreserveFlight(flight: FlightRequest) { | |
if (Math.random() > 0.5) { | |
// Inject temporary failure | |
throw new Error(`Unable to remove flight reservation for flight ${flight.flightId} for passenger ${flight.passengerName} due to a temporary error`) | |
} | |
console.log(`Unreserved flight ${flight.flightId} for passenger ${flight.passengerName}`) | |
} | |
async function reserveCar(car: CarRequest): Promise<string> { | |
if (Math.random() > 0.5) { | |
// Inject temporary failure | |
throw new Error(`Unable to reserve car rental on day ${car.rentalDate} at pickup location ${car.pickupLocation} due to a temporary error`) | |
} | |
console.log(`Reserved car rental on day ${car.rentalDate} at pickup location ${car.pickupLocation}`) | |
return car.rentalDate + "-" + car.pickupLocation | |
} | |
async function confirmCar(carBookingId: string) { | |
console.log(`Confirm car with booking id ${carBookingId}`) | |
} | |
async function unreserveCar(car: CarRequest) { | |
console.log(`Unreserved car rental on day ${car.rentalDate} at pickup location ${car.pickupLocation}`) | |
} | |
async function doPayment(paymentId: string, payment: PaymentRequest) { | |
console.log(`Will try to execute payment ${paymentId} amount ${payment.amount} charging card ${payment.cardNumber}`) | |
if (Math.random() > 0.5) { | |
// Not enough money available, just throw exception and fail the saga | |
throw new TerminalError(`Card ${payment.cardNumber} has not enough money available, rejecting the booking`) | |
} | |
console.log("Payment executed!") | |
} | |
async function refundPayment(paymentId: string) { | |
console.log(`Refunding payment ${paymentId}`) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment