db-oracle is not flushing data

connection-pooling, node.js, oracle

Solution

You are obviously missing a transaction commit.

node-db does not need to expose a commit API because in most RDBMS (including Oracle), COMMIT is a valid query. Since the package allows the execution of arbitrary queries, commit/rollback are supposed to be done using a simple execute()

The code should be changed as follows:

pool.acquire(function(err, conn) {
  if (err)
    return sendError(res, err, 500);

  var q = conn.query().insert('FILES', fields, values);
  q.execute(function(err, result) {

    if (err || result.affected < 1 ) {
       pool.release(conn);
       return sendError(res, err, 500);
    }

    conn.query().execute("commit", function(err,result) {
      if (err) {
        pool.release(conn);
        return sendError(res, err, 500);
      }
      res.end('<ok />');
      pool.release(conn);
    });
  });
});

Problem

I'm working on a simple service using Node.js. It receives uploaded files, stores them on the disk and records some metadata on an Oracle table. I'm using the `db-oracle` package together with connection pooling, following this article: http://nodejsdb.org/2011/05/connection-pooling-node-db-with-generic-pool/ However, I've noticed that the data I insert is only sent to the Oracle database after the connection pool closes the idle connection, by calling its `disconnect()` method. Is there a way to flush the data before sending the 'OK' signal to my client? The way it is working now, a crash on my webservice or on Oracle itself can cause loss of data, and the client of my service would not know about it. I actually tested this by killing my app process after some uploads, and the data was indeed lost. Here's a simplified version of the code: ``` var express = require('express'); var app = module.exports = express.createServer(); app.post('/upload', handleUpload); app.listen(4001, function(){ console.log("Express server listening on port %d in %s mode", app.address().port, app.settings.env); }); function handleUpload(req, res) { res.contentType('application/xml'); var buf = ''; req.on('data', function(chunk) { buf += chunk; }); req.on('end', function() { saveUpload(req, res, buf); }); } function saveUpload(req, res, buf) { if (buf.length == 0) return sendError(res, 'No data supplied', 422); var payload = new Buffer(buf, 'base64'); files.save(payload, function(err, savedFile) { if (err) return sendError(res, 'Error while saving', 500); var obj = { ip: req.connection.remoteAddress, location: savedFile.path, created_at: new Date(), updated_at: new Date() }; var fields = ['IP', 'LOCATION', 'CREATED_AT', 'UPDATED_AT']; var values = fields.map(function(v) { return obj[v.toLowerCase()] }); pool.acquire(function(err, conn) { if (err) return sendError(res, err, 500); var q = conn.query().insert('FILES', fields, values); q.execute(function(err, result) { pool.release(conn); if (err) return sendError(res, err, 500); if (result.affected < 1) return sendError(res, 'Error saving the record', 500); // The next statement sends the final result to the client. // However, the new record was not yet flushed to the database. res.end('<ok />'); }); }); }); } function sendError(res, err, code) { console.log(err); res.send('<error>' + err + '</error>', code || 500); } ``` As a workaround, I've tried to implement a fake connection pool and release all acquired connections, but now my app is dying with the message: `pure virtual method calledAbort trap: 6` Here's the fake connection pooling: ``` var fakePool = { acquire: function(callback) { new oracle.Database(config.database).connect(function(err, server) { callback(err, this); }); }, release: function(conn) { conn.disconnect(); } }; ``` Just to be clear, I don't care about the fake connection pooler, it was just a dirty workaround. I want to be able to flush the data to Oracle before sending the 'OK' to my client. Btw I also opened a ticket on their Github: https://github.com/mariano/node-db-oracle/issues/38

Original source