pg-nest

Nest transactions easily with PostgreSQL.

postgres-nest-transaction

Nest transactions easily with PostgreSQL & Node.js. Designed for use with [pg][pg] on npm. [pg]: https://github.com/brianc/node-postgres

$ npm install pg-nest
pg          = require 'pg'
Transaction = require 'pg-nest'
url         = "postgres://user:password@localhost:5432/db"
 
# Retrieve a pooled client connection. 
pg.connect url(err, client, done) ->
 
  # Create a new transaction with the pooled pg client. 
  = new Transaction( clientdone )
 
  # Start a new transaction with auto savepoint, and insert our hero! 
  t.start (err) ->
    t.query "INSERT INTO Characters VALUES ('Finn', 'human')"(err) ->
 
      # Create a nested subtransaction with savepoint, and continue... 
      t.nest (err, t2) ->
        t2.query "INSERT INTO Characters VALUES ('Ice King', 'wizard')"(err) ->
 
          # Wrong character! ~_~ Cancel the subtransaction to rollback. 
          t2.cancel (err) ->
 
            # Commit our work on the parent transaction. 
            t.finish (err) ->
              console.log 'Saved Finn!' unless err
Class: Transaction
Constructor
new Transaction( client, done ) Creates a new transaction, using a pooled pg client.
Start / Nest
transaction.start(cb(err)) Starts a new transaction, with auto savepoint
transaction.nest(cb(err, nested)) Starts a nested subtransaction, with auto savepoint.
Query
transaction.query(args..., cb(err, result)) Syntactic sugar for client.query().
Restart / Cancel
transaction.restart(cb(err)) Restarts this transaction by rolling back to its savepoint.
transaction.cancel(cb(err)) Cancels this transaction, but allows any parents to continue.
transaction.cancelAll(cb(err)) Cancels both this transaction and all parents.
Finish / Finalize
transaction.finish(cb(err)) Completes work on this transaction.
transaction.finalize(lastErr, cb(err)) Completes or cancels, depending on an error status.

Creates a new transaction, using a pooled pg client.

pg          = require 'pg'
Transaction = require 'pg-nest'
 
pg.connect url(err, client, done) ->
  = new Transaction( clientdone )

Just pass the client instance and done() function provided by pg.connect().
When the transaction completes, it will automatically release the client by calling done().
See the pg docs on pg.connect() for details.

Starts the new (or nested) transaction, with an auto savepoint.

= new Transaction clientdone
t.start (err) ->
  t.query "SELECT * FROM Characters"(err, result) ->
    console.log result.rows

Starts a nested subtransaction, with its own savepoint.

Since PostgreSQL lacks true subtransactions, this module simulates them with savepoints.

= new Transaction clientdone
t.start (err) ->
  t.nest (err, t2) ->
    t2.query "SELECT * FROM Characters"(err, result) ->
      console.log result.rows

Syntactic sugar for pg's client.query().

The pg module's client.query() is quite versatile, supporting simple or parameterized queries, and prepared statements.

query = "SELECT * FROM Characters"
t.query query(err, result) ->
  console.log result.rows

See the [pg docs][pg-client] on Client.query() for details. [pg-client]: https://github.com/brianc/node-postgres/wiki/Client

Params

  • text String The query text (for simple queries).
  • values Array An array of values (for parameterized queries).
  • config Object A configuration object (for parameterized queries or prepared statements).
  • callback(err, result) Function Called with the query result or error.

Restarts this transaction by rolling back to its savepoint.
When called on subtransactions, only the subtransaction is undone.

# Start transaction 
t.start (err) ->
  console.log "Started!"
 
  # Run queries... 
 
  # Restart to rollback to savepoint 
  t.restart (err) ->
    console.log "Restarted!"

Cancels this transaction, but allows any parents to continue.

t.cancel (err) ->
  console.log "Canceled this transaction."

Cancels this transaction (and any parents) completely.

t.cancelAll (err) ->
  console.log "Canceled this and parent transactions!"

Completes work on this transaction.

This commits if called on a top-level transaction, or just releases the savepoint if called on a subtransaction.

t.finish (err) ->
  console.log "Committed the transaction" unless err

Finalizes (finish or cancel) this transaction depending on a final error.

Simply a convenience to replace branching calls to .cancel() or finish().
Just give finalize() your last error, and it branches for you.

It propagates any error to the callback, including lastErr.

Instead of this:

t.query "INSERT INTO Foo VALUES ('bar', 'baz');"(lastErr) ->
  if lastErr
    t.cancel (err) ->
      console.log 'error!'
      doLastThing()
  else
    t.finish (err) ->
      console.log 'done!'
      doLastThing()

You can write:

t.query "INSERT INTO Foo VALUES ('bar', 'baz');"(lastErr) ->
  t.finalize lastErr(err) ->
    console.log if err then 'error!' else 'done!'
    doLastThing()

Params

  • lastErr Error If present then .cancel(), otherwise .finish().
  • callback(err) Function Called on completion or error.

MIT