npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

multiple-transaction-manager

v1.0.5

Published

Multiple Transaction Manager

Readme

multiple-transaction-manager

Multiple transaction manager library provides sequential execution of provided tasks from various transactional contexts. All contexts commit if the workflow completes without any exception, otherwise, all contexts are signalled to rollback in the presented order.

Features

  • A lightweight plain TypeScript library
  • Powered by provided contexts
  • Easy to deploy/integrate

Install

npm install multiple-transaction-manager

See the context pages for their installation commands.

Usage

The basic library provides the FunctionContext class which can be used to create a basic workflow. However more complex scenarios can be handled by using the additional contexts. Please refer the example project for a more detailed use case of the library. (https://github.com/kaplanke/mtxn-example)


    // init manager & context
    const txnMngr: MultiTxnMngr = new MultiTxnMngr();
    const functionContext = new FunctionContext(txnMngr);

    // Add a task for selecting Bob, Dave, or Kevin randomly
    const randTask: Task = functionContext.addTask((task) => {
        task.result = ["Bob", "Kevin", "Dave"][Math.floor(Math.random() * 3)];
        logger.info(task.result + " is selected");
        return Promise.resolve(task);
    });

    // Add a pop task that will add the proper task on the fly... 
    functionContext.addCondTask((_) => {
        if (randTask.getResult() === "Kevin") { // It' OK Kevin
            return CondTaskRet.BREAK();
        } else if (randTask.getResult() === "Dave") { // Bad Dave
            return CondTaskRet.ROLLBACK("No worries, this is expected for Dave...");
        }
        return CondTaskRet.CONTINUE(); // Bob 
    });

    // Add third step. Should not execute if Dave is selected
    functionContext.addTask(
        (task) => { return new Promise((resolve, _) => { console.log("Executing 3"); resolve(task) }); },
        null, // optional params
        (task) => { return new Promise((resolve, _) => { console.log("On Txn Commit 3"); resolve(task); }); },
        (task) => { return new Promise((resolve, _) => { console.log("On Txn Rollback 3"); resolve(task); }); }
    );

    txnMngr.exec().then(_ => {
        expect(randTask.getResult()).not.toBe("Dave");
    }).catch(err => { 
        logger.debug(err);
        expect(randTask.getResult()).toBe("Dave");
    });

The expected output:

If Dave is randomly selected

[INFO] default - Dave is selected
[DEBUG] MultiTxnMngr - Transaction quitting with rollback!
[ERROR] MultiTxnMngr - Transaction chain failed. Please see previous errors.
[INFO] MultiTxnMngr - Transaction chain rollbacked.
[DEBUG] default - No worries, this is expected for Dave...

If Kevin is randomly selected

[INFO] default - Kevin is selected
[DEBUG] MultiTxnMngr - Transaction quitting without rollback...
[INFO] MultiTxnMngr - Transaction chain completed.

If Bob is randomly selected

[INFO] default - Bob is selected
[DEBUG] MultiTxnMngr - Condition OK. Continuing transaction...
Executing 3.
On Txn Commit 3
[INFO] MultiTxnMngr - Transaction chain completed.

API

Interfaces

multiple-transaction-manager has two interfaces. Although the basic library provides FunctionContext and additional contexts are already available for different transaction providers like MySQL and MongoDB, you can create your own transaction provider by implementing those interfaces.

Context

export interface Context {
    init(): Promise<Context>;
    commit(): Promise<Context>;
    rollback(): Promise<Context>;
    isInitialized(): boolean;
    getName(): string;
}

init()

Called once by the transaction manager for initializing the transaction.

  • Returns: {Promise<Context>} A promise that resolves to the context instance.

commit()

Called once by the transaction manager after successful completion of all tasks.

  • Returns: {Promise<Context>} A promise that resolves to the context instance.

rollback()

Called once by the transaction manager if any of the tasks failed.

  • Returns: {Promise<Context>} A promise that resolves to the context instance.

isInitialized()

Called by transaction manager before each task execution to check if the transaction is already initialized.

  • Returns: {Promise<Context>} A promise that resolves to the context instance.

getName()

  • Returns: {string} The unique name for the context instance.

Task

export interface Task {
    getContext(): Context;
    exec(): Promise<Task>;
    getResult(): any;
}

getContext()

  • Returns: {Context} The task's context.

exec()

Calls the function provided in the execFunc property of the task.

  • Returns: {Promise<Task>} A promise that resolves to the task instance.

getResult()

  • Returns: {any} the result of the task, if any.

Classes

MultiTxnMngr

constructor()

  • Returns: {MultiTxnMngr} The created MultiTxnMngr instance.

FunctionContext

constructor(txnMngr)

  • txnMngr: {MultiTxnMngr} The multiple transaction manager to bind with the context.
  • Returns: {FunctionContext} The created FunctionContext instance.

addTask(execFunc, params, commitFunc, rollbackFunc)

Adds a function task to the transaction manager.

  • execFunc: {(task: FunctionTask) => Promise<FunctionTask>} The function to execute during the workflow.
  • params: {Function | Object} Parameter to pass to the fnExec function. Can be null.
  • commitFunc: {(task: FunctionTask) => Promise<FunctionTask>} Optional function to execute during commit phase.
  • rollbackFunc: {(task: FunctionTask) => Promise<FunctionTask>} Optional function to execute during rollback phase.
  • Returns: {FunctionTask} The created FunctionTask instance.

addPopTask(popTask)

Adds a task which will generate an array of additional tasks to inject to the task list of the transaction manager. This function is useful to add conditional tasks to the execution list.

  • popTask: {(task: PopTask) => Task[]} The function that will generate additional tasks to add to the task list.

FunctionTask

constructor(context, execFunc, params, commitFunc, rollbackFunc)

  • context: {Context} The FunctionContext to to bind with the task.
  • execFunc: {(task: FunctionTask) => Promise<FunctionTask>} The main function to execute.
  • params: {unknown} Optional parameter object.
  • commitFunc: {(task: FunctionTask) => Promise<FunctionTask>} Optional function to execute during commit phase.
  • rollbackFunc: {(task: FunctionTask) => Promise<FunctionTask>} Optional function to execute during rollback phase.
  • Returns: {FunctionTask} The created FunctionTask instance.

PopTask

constructor(context, popFunc)

  • context: {Context} The FunctionContext to to bind with the task.
  • popFunc: {(task: PopTask) => Task[]} The function that will generate additional tasks to add to the task list.
  • Returns: {PopTask} The created PopTask instance.

CondTask

constructor(context, condFunc)

  • context: {Context} The FunctionContext to to bind with the task.
  • condFunc: {(task: CondTask) => CondTaskRet} The function that will evaluate the current condition and return the proper CondTaskRet.
  • Returns: {CondTask} The created CondTaskRet instance.

CondTaskRet

CondTaskRet.CONTINUE()

  • Returns: {CondTaskRet} The created CondTaskRet instance which allows the transaction flow without any intervention.

CondTaskRet.BREAK(params)

  • params: {object} Additional parameters which will be available as the result of the task after execution.
  • Returns: {CondTaskRet} The created CondTaskRet instance which makes the transaction to commit immediately without executing any consecutive tasks.

CondTaskRet.ROLLBACK(msg, params)

  • msg: {Context} The FunctionContext to to bind with the task.
  • params: {object} Additional parameters which will be available as the result of the task after execution.
  • Returns: {CondTaskRet} The created CondTaskRet instance which makes the transaction to rollback immediately with the provided message.

Contexts

Currently the following contexts are available;

You can leave comment to vote for development of a new context. https://github.com/users/kaplanke/projects/2

Discussions

Although multiple-transaction-manager manages the transactions under normal circumstances, there are still some critical point to consider during the execution of the workflow;

  • If an error occurs during the commit phase of a context, the rollback action is triggered for the entire MultiTxnMngr which may not be able to rollback already committed contexts.
  • You may still have deadlocks during the execution of the workflow if you use the same transaction provider for multiple contexts. (For example if you use Sequelize Context and MySql context at the same MultiTxnMngr, you may block both contexts during a reciprocal update statement.)
  • If you like to pass parameters that depends on the execution of the previous tasks, you should use a function ( ()=>{} ) instead of an object. (There is an exception for Redis context, please see the context page for details.)