Pertanyaan db-oracle tidak membilas data


Saya sedang mengerjakan layanan sederhana menggunakan Node.js. Ini menerima file yang diunggah, menyimpannya di disk dan mencatat beberapa metadata di tabel Oracle. Saya menggunakan db-oracle paket bersama dengan penggabungan koneksi, mengikuti artikel ini: http://nodejsdb.org/2011/05/connection-pooling-node-db-with-generic-pool/

Namun, saya perhatikan bahwa data yang saya masukkan hanya dikirim ke database Oracle setelah kolam koneksi menutup koneksi kosong, dengan memanggil disconnect() metode.

Apakah ada cara untuk menyiram data sebelum mengirim sinyal 'OK' ke klien saya? Cara kerjanya sekarang, crash pada webservice saya atau pada Oracle itu sendiri dapat menyebabkan hilangnya data, dan klien layanan saya tidak akan mengetahuinya. Saya benar-benar menguji ini dengan membunuh proses aplikasi saya setelah beberapa unggahan, dan datanya memang hilang.

Berikut ini versi kode yang disederhanakan:

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

Sebagai solusi, saya sudah mencoba mengimplementasikan kolam koneksi palsu dan melepaskan semua koneksi yang didapat, tetapi sekarang aplikasi saya mati dengan pesan: pure virtual method calledAbort trap: 6

Berikut adalah penggabungan koneksi palsu:

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

Hanya untuk menjadi jelas, saya tidak peduli tentang pooler koneksi palsu, itu hanya solusi kotor. Saya ingin dapat mem-flush data ke Oracle sebelum mengirim 'OK' ke klien saya.

Btw Saya juga membuka tiket di Github mereka: https://github.com/mariano/node-db-oracle/issues/38


5
2018-05-30 03:02


asal


Jawaban:


Anda jelas tidak memiliki komitmen transaksi.

node-db tidak perlu mengekspos API komit karena di sebagian besar RDBMS (termasuk Oracle), COMMIT adalah query yang valid. Karena paket memungkinkan eksekusi pertanyaan arbitrer, commit / rollback seharusnya dilakukan menggunakan eksekusi sederhana ()

Kode harus diubah sebagai berikut:

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

6
2018-06-23 14:41



Ini bukan jawaban yang tepat untuk pertanyaan Anda, tetapi lihatlah node-oracle paket. Ini tidak memiliki koneksi penggabungan, tetapi commit / rollback fungsionalitas setidaknya dapat dikendalikan dari kode. Dan Anda selalu dapat mencampurnya dengan solusi kolam generik seperti node-pool.


1
2018-06-20 12:28