使用 MongoDB 连接池的 NodeJS 一次性脚本 - 如何终止?
NodeJS one-shot script using MongoDB connection pooling - how to terminate?
我知道 MongoDB 像这样的单例数据库连接类型的 NodeJS 中的连接池的最佳实践
var db = null;
var connection = function getDBConnection(callback) {
if(db) { callback(null, db) } else { MongoClient.connect( .... ) }
}
module.exports = getDBConnection;
然而,我现在无法理解的是如何在一次性脚本中处理这个问题,比如说,对某个数据库集合的文档进行一些预初始化:
getDBConnection(function (err, database) {
var collection = database.collection("objects");
var allObjectsArray = collection.find( /* ... */
).toArray(function (err, objects) {
if(err != null) console.log(err);
assert.equal(null, err);
_.each(objects, function (item) {
collection.update(
{ id: item.id},
{ $set: { /* ... */ }},
function (err, result) {
if(err != null) console.log(err);
assert.equal(null, err);
}
);
});
// database.close(); <-- this fails with "MongoError: Connection Closed By Application", thrown by the update callback
});
// database.close(); <-- this fails too, thrown by the toArray callback
});
如果我那样调用脚本,它永远不会终止,因为连接仍然打开。如果我关闭底部的连接,它会失败,因为连接已关闭。
考虑到为每次更新打开一个新连接并不是一个真正的选择,我错过了什么?保持连接打开对于 web 应用程序可能没问题,但对于从 shell 脚本调用的一次性脚本,这真的行不通,对吗?
抱歉,如果之前出现过这个问题,我已经进行了一些研究,但还没有完全能够为我想出一个可行的答案...
谢谢!
朱利安
作为 "pooled connection" 有代码 运行 保持连接活动并在驱动程序连接下需要时在池中建立更多连接。与各种 "server code" 方法非常相似,事件循环处理程序已被调用,并且在取消注册之前,该过程不会在代码末尾退出。
因此,您在执行完所有代码后调用的两个选择是:
调用 db.close()
或在您的代码上下文中特别是 database.close()
完成所有操作后。
调用 process.exit()
这是 node.js 应用程序中的通用调用,它将关闭整个进程并因此停止任何其他当前事件循环代码。如果您希望代码在某处 "shell integrated" 并查找退出状态,这实际上为您提供了在退出时抛出错误的选项。
或者两者都调用。 db.close()
将允许执行到下一行代码,无论你放在那里什么也将 运行.
但是你必须等到所有的东西都被调用,所以你不能使用中间有异步代码的同步循环:
async.each(objects,function(item,callback) {
collection.update(
{ "_id": item._id },
{
// updates
},
callback
);
},function(err) {
if (err) throw err;
database.close();
});
我知道 MongoDB 像这样的单例数据库连接类型的 NodeJS 中的连接池的最佳实践
var db = null;
var connection = function getDBConnection(callback) {
if(db) { callback(null, db) } else { MongoClient.connect( .... ) }
}
module.exports = getDBConnection;
然而,我现在无法理解的是如何在一次性脚本中处理这个问题,比如说,对某个数据库集合的文档进行一些预初始化:
getDBConnection(function (err, database) {
var collection = database.collection("objects");
var allObjectsArray = collection.find( /* ... */
).toArray(function (err, objects) {
if(err != null) console.log(err);
assert.equal(null, err);
_.each(objects, function (item) {
collection.update(
{ id: item.id},
{ $set: { /* ... */ }},
function (err, result) {
if(err != null) console.log(err);
assert.equal(null, err);
}
);
});
// database.close(); <-- this fails with "MongoError: Connection Closed By Application", thrown by the update callback
});
// database.close(); <-- this fails too, thrown by the toArray callback
});
如果我那样调用脚本,它永远不会终止,因为连接仍然打开。如果我关闭底部的连接,它会失败,因为连接已关闭。
考虑到为每次更新打开一个新连接并不是一个真正的选择,我错过了什么?保持连接打开对于 web 应用程序可能没问题,但对于从 shell 脚本调用的一次性脚本,这真的行不通,对吗?
抱歉,如果之前出现过这个问题,我已经进行了一些研究,但还没有完全能够为我想出一个可行的答案...
谢谢! 朱利安
作为 "pooled connection" 有代码 运行 保持连接活动并在驱动程序连接下需要时在池中建立更多连接。与各种 "server code" 方法非常相似,事件循环处理程序已被调用,并且在取消注册之前,该过程不会在代码末尾退出。
因此,您在执行完所有代码后调用的两个选择是:
调用
db.close()
或在您的代码上下文中特别是database.close()
完成所有操作后。调用
process.exit()
这是 node.js 应用程序中的通用调用,它将关闭整个进程并因此停止任何其他当前事件循环代码。如果您希望代码在某处 "shell integrated" 并查找退出状态,这实际上为您提供了在退出时抛出错误的选项。
或者两者都调用。 db.close()
将允许执行到下一行代码,无论你放在那里什么也将 运行.
但是你必须等到所有的东西都被调用,所以你不能使用中间有异步代码的同步循环:
async.each(objects,function(item,callback) {
collection.update(
{ "_id": item._id },
{
// updates
},
callback
);
},function(err) {
if (err) throw err;
database.close();
});