Skip to content

Instantly share code, notes, and snippets.

@icebob
Last active October 2, 2023 10:47
Show Gist options
  • Save icebob/c75d4d532c0d7783eb924a96110b9020 to your computer and use it in GitHub Desktop.
Save icebob/c75d4d532c0d7783eb924a96110b9020 to your computer and use it in GitHub Desktop.

Revisions

  1. icebob revised this gist Mar 26, 2019. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion saga-sample.js
    Original file line number Diff line number Diff line change
    @@ -36,7 +36,7 @@ const SagaMiddleware = function() {
    return res;
    })
    .catch(err => {
    if (ctx.meta.$saga && ctx.meta.$saga.compensations) {
    if (ctx.meta.$saga && ctx.meta.$saga.compensations) {
    // Start compensating
    ctx.service.logger.warn(chalk.red.bold("Some error occured. Start compensating..."));
    ctx.service.logger.info(ctx.meta.$saga.compensations);
  2. icebob revised this gist Mar 26, 2019. 1 changed file with 12 additions and 10 deletions.
    22 changes: 12 additions & 10 deletions saga-sample.js
    Original file line number Diff line number Diff line change
    @@ -36,16 +36,18 @@ const SagaMiddleware = function() {
    return res;
    })
    .catch(err => {
    // Start compensating
    ctx.service.logger.warn(chalk.red.bold("Some error occured. Start compensating..."));
    ctx.service.logger.info(ctx.meta.$saga.compensations);
    if (ctx.meta.$saga && Array.isArray(ctx.meta.$saga.compensations)) {
    return Promise.map(ctx.meta.$saga.compensations, item => {
    return ctx.call(item.action, item.params);
    }).then(() => {
    throw err;
    });
    }
    if (ctx.meta.$saga && ctx.meta.$saga.compensations) {
    // Start compensating
    ctx.service.logger.warn(chalk.red.bold("Some error occured. Start compensating..."));
    ctx.service.logger.info(ctx.meta.$saga.compensations);
    if (ctx.meta.$saga && Array.isArray(ctx.meta.$saga.compensations)) {
    return Promise.map(ctx.meta.$saga.compensations, item => {
    return ctx.call(item.action, item.params);
    }).then(() => {
    throw err;
    });
    }
    }

    throw err;
    });
  3. icebob revised this gist Mar 11, 2019. 1 changed file with 4 additions and 3 deletions.
    7 changes: 4 additions & 3 deletions saga-sample.js
    Original file line number Diff line number Diff line change
    @@ -135,14 +135,15 @@ broker.createService({
    }
    },
    handler(ctx) {
    this.logger.info(chalk.cyan.bold("Flight is booked."));
    return this.Promise.reject(new MoleculerError("Unable to book flight!"));
    /*return {

    this.logger.info(chalk.cyan.bold("Flight is booked."));
    return {
    id: 2,
    number: "SQ318",
    from: "SIN",
    to: "LHR"
    };*/
    };
    }
    },

  4. icebob revised this gist Mar 11, 2019. 1 changed file with 6 additions and 5 deletions.
    11 changes: 6 additions & 5 deletions saga-sample.js
    Original file line number Diff line number Diff line change
    @@ -37,7 +37,8 @@ const SagaMiddleware = function() {
    })
    .catch(err => {
    // Start compensating
    ctx.service.logger.warn(chalk.red.bold("Some error occured. Start compensating..."), ctx.meta.$saga.compensations);
    ctx.service.logger.warn(chalk.red.bold("Some error occured. Start compensating..."));
    ctx.service.logger.info(ctx.meta.$saga.compensations);
    if (ctx.meta.$saga && Array.isArray(ctx.meta.$saga.compensations)) {
    return Promise.map(ctx.meta.$saga.compensations, item => {
    return ctx.call(item.action, item.params);
    @@ -153,11 +154,11 @@ broker.createService({
    }
    });

    // --- TRIP SERVICE ---
    // --- TRIP SAGA SERVICE ---
    broker.createService({
    name: "trips",
    name: "trip-saga",
    actions: {
    create: {
    createTrip: {
    saga: true,
    async handler(ctx) {
    try {
    @@ -179,7 +180,7 @@ async function start() {

    //broker.repl();

    await broker.call("trips.create");
    await broker.call("trip-saga.createTrip");
    }

    start();
  5. icebob created this gist Mar 11, 2019.
    185 changes: 185 additions & 0 deletions saga-sample.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,185 @@
    "use strict";

    const _ = require("lodash");
    const chalk = require("chalk");
    const Promise = require("bluebird");
    const ServiceBroker = require("../src/service-broker");
    const { MoleculerError } = require("../src/errors");

    // --- SAGA MIDDLEWARE ---
    const SagaMiddleware = function() {
    return {
    localAction(handler, action) {
    if (action.saga) {
    const opts = action.saga;
    return function sagaHandler(ctx) {
    return handler(ctx)
    .then(res => {
    if (opts.compensation) {
    if (!ctx.meta.$saga) {
    ctx.meta.$saga = {
    compensations: []
    };
    }

    const comp = {
    action: opts.compensation.action
    };
    if (opts.compensation.params) {
    comp.params = opts.compensation.params.reduce((a, b) => {
    _.set(a, b, _.get(res, b));
    return a;
    }, {});
    }
    ctx.meta.$saga.compensations.unshift(comp);
    }
    return res;
    })
    .catch(err => {
    // Start compensating
    ctx.service.logger.warn(chalk.red.bold("Some error occured. Start compensating..."), ctx.meta.$saga.compensations);
    if (ctx.meta.$saga && Array.isArray(ctx.meta.$saga.compensations)) {
    return Promise.map(ctx.meta.$saga.compensations, item => {
    return ctx.call(item.action, item.params);
    }).then(() => {
    throw err;
    });
    }

    throw err;
    });
    };
    }

    return handler;
    }
    };
    };

    // --- BROKER ---
    const broker = new ServiceBroker({
    logFormatter: "short",
    middlewares: [
    SagaMiddleware()
    ]
    });

    // --- CARS SERVICE ---
    broker.createService({
    name: "cars",
    actions: {
    reserve: {
    saga: {
    compensation: {
    action: "cars.cancel",
    params: ["id"]
    }
    },
    handler(ctx) {
    this.logger.info(chalk.cyan.bold("Car is reserved."));
    return {
    id: 5,
    name: "Honda Civic"
    };
    }
    },

    cancel: {
    handler(ctx) {
    this.logger.info(chalk.yellow.bold(`Cancel car reservation of ID: ${ctx.params.id}`));
    }
    }
    }
    });

    // --- HOTELS SERVICE ---
    broker.createService({
    name: "hotels",
    actions: {
    book: {
    saga: {
    compensation: {
    action: "hotels.cancel",
    params: ["id"]
    }
    },
    handler(ctx) {
    this.logger.info(chalk.cyan.bold("Hotel is booked."));
    return {
    id: 8,
    name: "Holiday Inn",
    from: "2019-08-10",
    to: "2019-08-18"
    };
    }
    },

    cancel: {
    handler(ctx) {
    this.logger.info(chalk.yellow.bold(`Cancel hotel reservation of ID: ${ctx.params.id}`));
    }
    }
    }
    });

    // --- FLIGHTS SERVICE ---
    broker.createService({
    name: "flights",
    actions: {
    book: {
    saga: {
    compensation: {
    action: "flights.cancel",
    params: ["id"]
    }
    },
    handler(ctx) {
    this.logger.info(chalk.cyan.bold("Flight is booked."));
    return this.Promise.reject(new MoleculerError("Unable to book flight!"));
    /*return {
    id: 2,
    number: "SQ318",
    from: "SIN",
    to: "LHR"
    };*/
    }
    },

    cancel: {
    handler(ctx) {
    this.logger.info(chalk.yellow.bold(`Cancel flight ticket of ID: ${ctx.params.id}`));
    }
    }
    }
    });

    // --- TRIP SERVICE ---
    broker.createService({
    name: "trips",
    actions: {
    create: {
    saga: true,
    async handler(ctx) {
    try {
    const car = await ctx.call("cars.reserve");
    const hotel = await ctx.call("hotels.book");
    const flight = await ctx.call("flights.book");
    this.logger.info(chalk.green.bold("Trip is created successfully: "), { car, flight, hotel });
    } catch(err) {
    this.logger.error(chalk.red.bold("Trip couldn't be created. Reason: "), err.message);
    }
    }
    }
    }
    });

    // --- START ---
    async function start() {
    await broker.start();

    //broker.repl();

    await broker.call("trips.create");
    }

    start();