2012-05-30 12 views
5

Sto lavorando su un servizio semplice utilizzando Node.js. Riceve i file caricati, li memorizza sul disco e registra alcuni metadati su una tabella Oracle. Sto usando il pacchetto db-oracle insieme con il pool di connessioni, a seguito di questo articolo: http://nodejsdb.org/2011/05/connection-pooling-node-db-with-generic-pool/db-oracle non sta scaricando dati

Tuttavia, ho notato che i dati inserisco viene inviato solo al database Oracle dopo il pool di connessioni chiude la connessione inattiva, chiamando il suo metodo disconnect().

C'è un modo per scaricare i dati prima di inviare il segnale "OK" al mio client? Il modo in cui funziona ora, un arresto anomalo sul mio servizio web o su Oracle stesso può causare la perdita di dati e il client del mio servizio non lo saprebbe. In realtà ho provato questo uccidendo il mio processo di app dopo alcuni caricamenti, e i dati sono stati effettivamente persi.

Ecco una versione semplificata del codice:

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); 
} 

Per aggirare il problema, ho cercato di implementare un pool di connessioni falso e rilasciare tutte le connessioni acquisite, ma ora la mia app è morendo con il messaggio: pure virtual method calledAbort trap: 6

Ecco il falso pool di connessioni:

var fakePool = { 
    acquire: function(callback) { 
    new oracle.Database(config.database).connect(function(err, server) { 
     callback(err, this); 
    }); 
    }, 
    release: function(conn) { 
    conn.disconnect(); 
    } 
}; 

giusto per essere chiari, non mi interessa il Pooler collegamento falso, era solo un soluzione sporca. Desidero essere in grado di scaricare i dati su Oracle prima del inviando l''OK' al mio client.

Btw ho anche aperto un biglietto sul loro Github: https://github.com/mariano/node-db-oracle/issues/38

+0

non vedo alcun commettere in il codice ... –

+0

Sì, i pacchetti 'db-oracle' e' node-db' non ne espongono alcuno, AFAIK. Ho approfondito la documentazione e le fonti e non ho trovato alcun modo per eseguire esplicitamente un commit. Ho trovato, tuttavia, un metodo 'commit' sui documenti OCCI. Forse dovrò sborsare il progetto ed esporre il metodo di commit? –

+0

Questi pacchetti dipendono forse dal (ugh!) Comportamento di auto-commit? –

risposta

6

Manca ovviamente un commit di transazione.

node-db non ha bisogno di esporre un'API di commit perché nella maggior parte degli RDBMS (incluso Oracle), COMMIT è una query valida. Poiché il pacchetto permette l'esecuzione di query arbitrarie, commit/rollback si suppone essere fatto con un semplice execute()

Il codice dovrebbe essere modificato come segue:

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); 
    }); 
    }); 
}); 
+0

Farò un tentativo, grazie! –

1

Questa non è una risposta esatta alla tua domanda, ma hanno uno sguardo al node-oracle pacchetto. Manca il pool di connessioni, ma la sua funzionalità commit/rollback può essere controllata almeno dal codice. E puoi sempre mescolarlo con un generic pool solution such as node-pool.

+0

Grazie, @ npe ... Darò anche a 'node-oracle' un tentativo. La parte triste è che non è integrato con 'node-db'. –

Problemi correlati