【发布时间】:2017-08-24 07:32:35
【问题描述】:
我有现有的管理 api 代码,我已将其简化为用于测试目的(这可行):
admin.database().ref('/dropbox').on('child_added', function (childSnap) {
let item, itemRef = childSnap.ref;
console.log(`Item: ${JSON.stringify(childSnap.val())} at ${childSnap.key}`);
console.log(`Item ref: ${itemRef.toString()}`);
itemRef.transaction(function (value) {
console.log(`Value: ${JSON.stringify(value)}`);
if (value) {
item = value;
return null;
}
}).then(function (resolution) {
console.log(`Txn resolution: ${resolution.committed ? 'committed' : 'NOT-COMMITTED'}`);
if (resolution.committed) {
// process item
console.log(`Process: ${JSON.stringify(item)}`);
} else {
// assume that item must have been removed by someone else
}
}).catch(function (err) {
console.log(`Txn error: ${JSON.stringify(err, null, 2)}`);
});
});
当我跑步时:
firebase 数据库:推送 /dropbox
控制台输出为:
Item: {"test":"abc123"} at -KgTpp3FzgbLUrMNofNZ
Item ref: https://cloud-function-txn-test.firebaseio.com/dropbox/-KgTpp3FzgbLUrMNofNZ
Value: {"test":"abc123"}
Txn resolution: committed
Process: {"test":"abc123"}
我一直在尝试将我的代码和此示例移至云函数。我意识到 .on('child_added', f) 和 .onWrite(f) 以不同的方式处理现有数据,但我无法让事务代码正常工作。传递给我的事务函数的参数始终为空。
作为云功能(这不起作用):
exports.receiveAndRemove = functions.database.ref('/dropbox/{entryId}').onWrite(function (event) {
if (!event.data.exists()) {
return;
}
let item, itemRef = event.data.adminRef;
console.log(`Item: ${JSON.stringify(event.data.val())} at ${event.data.key}`);
console.log(`Item ref: ${itemRef.toString()}`);
itemRef.transaction(function (value) {
console.log(`Value: ${JSON.stringify(value)}`);
if (value) {
item = value;
return null;
}
}).then(function (resolution) {
console.log(`Txn resolution: ${resolution.committed ? 'committed' : 'NOT-COMMITTED'}`);
if (resolution.committed) {
// process item
console.log(`Process: ${JSON.stringify(item)}`);
} else {
// bad to assume here that item must have been removed by someone else
}
}).catch(function (err) {
console.log(`Txn error: ${JSON.stringify(err, null, 2)}`);
});
});
由于某种原因,交易永远不会删除该项目。日志输出:
2017-03-30T10:51:19.387565284Z D receiveAndRemove: Function execution started
2017-03-30T10:51:19.395Z I receiveAndRemove: Item: {"test":"abc123"} at -KgTpp3FzgbLUrMNofNZ
2017-03-30T10:51:19.395Z I receiveAndRemove: Item ref: https://cloud-function-txn-test.firebaseio.com/dropbox/-KgTpp3FzgbLUrMNofNZ
2017-03-30T10:51:19.396Z I receiveAndRemove: Value: null
2017-03-30T10:51:19.396Z I receiveAndRemove: Txn resolution: NOT-COMMITTED
2017-03-30T10:51:19.418446269Z D receiveAndRemove: Function execution took 32 ms, finished with status: 'ok'
当然,云功能无法移除项目,并且由于事务没有提交移除,因此也不会处理该项目。我希望两者都会发生,并且即使节点服务器版本正在运行,我也希望此代码能够正常工作。无论在云和/或我的服务器中有多少实例正在运行,这些项目都应该只处理一次。
我缺少的云功能有什么细微差别吗?我在处理事务时是否存在错误或不适用于云功能?
完整来源:https://github.com/mscalora/cloud-function-txn-test.git
【问题讨论】:
-
尝试通过在
itemRef.transaction前面添加return来返回从事务返回的承诺。 Cloud Function 不会在您的代码示例中停留很长时间,因为您没有返回 promise,它告诉 Cloud Function 等待直到它被解决。不确定它会解决你的问题,但它可能会。 -
我会尝试,但日志显示事务回调运行和 then 也运行
-
返回承诺并没有改变行为,日志看起来完全一样。交易回调为空。
标签: javascript firebase transactions firebase-realtime-database google-cloud-functions