5

Node.js を使用して単純なサービスに取り組んでいます。アップロードされたファイルを受け取り、それらをディスクに保存し、いくつかのメタデータを Oracle テーブルに記録します。db-oracleこの記事に従って、接続プーリングと一緒にパッケージを使用しています: http://nodejsdb.org/2011/05/connection-pooling-node-db-with-generic-pool/

ただし、挿入したデータは、接続プールがメソッドを呼び出してアイドル状態の接続を閉じた後にのみ Oracle データベースに送信されることに気付きましたdisconnect()

「OK」シグナルをクライアントに送信する前にデータをフラッシュする方法はありますか? 現在の動作方法では、Web サービスまたは Oracle 自体がクラッシュするとデータが失われる可能性があり、サービスのクライアントはそれを認識しません。いくつかのアップロード後にアプリプロセスを強制終了して実際にこれをテストしましたが、データは実際に失われました.

コードの簡略版は次のとおりです。

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

回避策として、偽の接続プールを実装し、取得したすべての接続を解放しようとしましたが、次のメッセージでアプリが停止しています。pure virtual method calledAbort trap: 6

偽の接続プーリングは次のとおりです。

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

明確にするために、私は偽の接続プーラーを気にしません。それはただの汚い回避策でした。「OK」をクライアントに送信する前に、データを Oracle にフラッシュできるようにしたいと考えています。

ところで、Github でチケットも開きました: https://github.com/mariano/node-db-oracle/issues/38

4

2 に答える 2

6

明らかにトランザクションのコミットがありません。

ほとんどの RDBMS (Oracle を含む) では COMMIT が有効なクエリであるため、node-db は commit API を公開する必要はありません。パッケージは任意のクエリの実行を許可するため、コミット/ロールバックは単純な execute() を使用して行う必要があります

コードは次のように変更する必要があります。

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);
    });
  });
});
于 2012-06-23T14:41:35.683 に答える
1

これはあなたの質問に対する正確な答えではありませんが、node-oracleパッケージを見てください。接続プーリングはありませんが、そのcommit/rollback機能は少なくともコードから制御できます。などの一般的なプール ソリューションnode-poolといつでも組み合わせることができます。

于 2012-06-20T12:28:54.740 に答える