简体   繁体   中英

Transaction in feathersjs using Objection ORM

feathers-objection - A service adapter for Objection.js - A minimal SQL ORM built on top of Knex.

Transactions are atomic and isolated units of work in relational databases.

We want to create and use transaction in feathersjs application generated using the Feathers CLI.

But

We were not able to figure out how to create a transaction object and pass it to series of service calls using the transaction params operator and how to use await transaction.trx.commit() and await transaction.trx.rollback() .

Help is required for the same.

Was able to achieve transaction in feathersjs using objection ORM.

Findings are as follows.

transaction-hooks

const {transaction} = require('objection');
// Use this hook to manipulate incoming or outgoing data.
// For more information on hooks see: http://docs.feathersjs.com/api/hooks.html
// eslint-disable-next-line no-unused-vars
const start = (options = {}) => {
  return async context => {
    const { service } = context;
    const Model = service.Model;
    const trx = await transaction.start(Model); // use Model if you have installed a knex instance globally using the Model.knex() method, otherwise use Model.knex()
    context.params.transaction = { trx };
    return context;
  };
};
const commit = (options = {}) => {
  return async context => {
    const { transaction } = context.params;
    await transaction.trx.commit();
    return context;
  };
};
const rollback = (options = {}) => {
  return async context => {
    const { transaction } = context.params;
    await transaction.trx.rollback();
  };
};
module.exports = {
  _transaction: {
    start,
    commit,
    rollback
  }
};

Then in your service.hooks use the following:

const {_transaction} = require('../../hooks/transaction-hooks');
module.exports = {
  before: {
    all: [],
    find: [],
    get: [],
    create: [_transaction.start(),createRideData],
    update: [],
    patch: [],
    remove: []
  },
  after: {
    all: [],
    find: [],
    get: [],
    create: [updateRideRequestStatus, _transaction.commit()],
    update: [],
    patch: [],
    remove: []
  },
  error: {
    all: [],
    find: [],
    get: [],
    create: [_transaction.rollback()],
    update: [],
    patch: [],
    remove: []
  }
};

One can also start transaction with the knex instance:

const start = (options = {}) => {
  return async context => {
    const { service, app } = context;
    const knex = app.get('knex');
    const trx = await transaction.start(knex);
    context.params = {
      ...context.params,
      transaction: {
        trx
      }
    }
    return context;
  };
};

Check knex.transcationProvider() example from https://knexjs.org/#Transactions

However there might be a bug in documentation in the part where await trx.commit() and await trx.rollback() are called.

Safer way would be to just call either of those without await and await trx.executionPromise to get transaction result / error if it was rolled back.

Transaction documentation in knex is currently quite messy.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM