2012-05-30 1 views
5

Я работаю над простым сервисом, используя Node.js. Он получает загруженные файлы, сохраняет их на диске и записывает некоторые метаданные в таблице Oracle. Я использую пакет db-oracle вместе с пулом соединений, следующий за этой статьей: http://nodejsdb.org/2011/05/connection-pooling-node-db-with-generic-pool/db-oracle не очищает данные

Однако я заметил, что данные, которые я вставляю, отправляются только в базу данных Oracle после того, как пул соединений закрывает незанятое соединение, вызывая его метод disconnect().

Есть ли способ сбросить данные перед отправкой сигнала «OK» моему клиенту? То, как он работает сейчас, сбой на моем веб-сервисе или на самом 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(); 
    } 
}; 

Просто чтобы быть ясно, я не забочусь о поддельной связи Pooler, это было просто грязный обходной путь. Я хочу, чтобы вы могли очистить данные до Oracle до, отправив «OK» моему клиенту.

Btw Я также открыл билет на их Github: https://github.com/mariano/node-db-oracle/issues/38

+0

Я не вижу никакой фиксации в код ... –

+0

Да, пакеты 'db-oracle' и' node-db' не выставляются, AFAIK. Я углубился в их документацию и источники и не нашел способа явно выполнить фиксацию. Однако я нашел метод «commit» в документах OCCI. Может быть, мне придется разветвить проект и разоблачить метод фиксации? –

+0

Возможно ли, чтобы эти пакеты зависели от (автоответчика) поведения? –

ответ

6

Вам явно не хватает транзакционного фиксации.

node-db не нужно раскрывать API-интерфейс фиксации, потому что в большинстве СУБД (включая Oracle) COMMIT является допустимым запросом. Поскольку пакет позволяет выполнять произвольные запросы, совершать/откат должны быть сделано с помощью простого выполнения()

Код должен быть изменен следующим образом:

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

Я попробую, спасибо! –

1

Это не точный ответ на ваш вопрос, но посмотрите на node-oracle пакет. Не хватает пула соединений, но его функциональность, по крайней мере, может управляться с помощью кода commit/rollback. И вы всегда можете смешивать его с generic pool solution such as node-pool.

+0

Спасибо, @ npe ... Я также дам 'node-oracle' попробовать. Печальная часть состоит в том, что она не интегрирована с 'node-db'. –

 Смежные вопросы

  • Нет связанных вопросов^_^