Skip to content

Commit

Permalink
Implement support for starting transactions without immediately execu…
Browse files Browse the repository at this point in the history
…ting them
  • Loading branch information
kibertoad committed Mar 9, 2019
1 parent 1da56a3 commit 90f496a
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 5 deletions.
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,6 @@ module.exports = {
env: {
node: true,
mocha: true,
es6: true,
},
};
15 changes: 14 additions & 1 deletion src/transaction.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@ export default class Transaction extends EventEmitter {
super();

const txid = (this.txid = uniqueId('trx'));
if (!container) {
this.initPromise = new Promise((resolve, reject) => {
this.initRejectFn = reject;
container = (transactor) => {
resolve(transactor);
};
});
}

this.client = client;
this.logger = client.logger;
Expand Down Expand Up @@ -67,7 +75,12 @@ export default class Transaction extends EventEmitter {
}
return null;
})
.catch((e) => this._rejecter(e));
.catch((e) => {
if (this.initRejectFn) {
this.initRejectFn();
}
return this._rejecter(e);
});

return new Promise((resolver, rejecter) => {
this._resolver = resolver;
Expand Down
15 changes: 12 additions & 3 deletions src/util/make-knex.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,21 @@ function initContext(knexFn) {
return batchInsert(this, table, batch, chunkSize);
},

// Runs a new transaction, taking a container and returning a promise
// for when the transaction is resolved.
// Creates a new transaction.
// If container is provided, returns a promise for when the transaction is resolved.
// If container is not provided, returns a promise with a transaction that is resolved
// when transaction is ready to be used.
transaction(container, config) {
const trx = this.client.transaction(container, config);
trx.userParams = this.userParams;
return trx;

if (container) {
return trx;
}
// If no container was passed, assume user wants to get a transaction and use it directly
else {
return trx.initPromise;
}
},

// Typically never needed, initializes the pool for a knex client.
Expand Down
21 changes: 21 additions & 0 deletions test/unit/knex.js
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,27 @@ describe('knex', () => {
});
});

it('supports direct retrieval of a transaction without a callback', (done) => {
const knex = Knex(sqliteConfig);
const trxPromise = knex.transaction();

trxPromise
.then((trx) => {
expect(trx.client.transacting).to.equal(true);
knex
.transacting(trx)
.select(knex.raw('SELECT 1 AS 1'))
.then((result) => {
expect(result).to.equal(1);
done();
});
return trx.commit();
})
.then(() => {
done();
});
});

it('creating transaction copy with user params should throw an error', (done) => {
const knex = Knex(sqliteConfig);

Expand Down
2 changes: 1 addition & 1 deletion types/knex.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ interface Knex extends Knex.QueryInterface {

raw: Knex.RawBuilder;
transaction<T>(
transactionScope: (trx: Knex.Transaction) => Promise<T> | Bluebird<T> | void
transactionScope?: (trx: Knex.Transaction) => Promise<T> | Bluebird<T> | void
): Bluebird<T>;
destroy(callback: Function): void;
destroy(): Bluebird<void>;
Expand Down

0 comments on commit 90f496a

Please sign in to comment.