作者:沉沉浮浮触涙水 | 来源:互联网 | 2023-02-08 09:13
我有现有的管理员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数据库:push/dropbox <<<'{"test":"abc123"}'
控制台输出是:
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)对待现有数据的方式不同,但我无法使交易代码正常工作.传递给我的事务函数的参数始终为null.
作为云功能(这不起作用):
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
1> jwngr..:
这里的问题是,在事务值为的情况下null
,您返回undefined
,这将取消事务.实际上,当值为null
Firebase可能会传递该值时,您需要处理该案例.这次潜水的原因有点与Firebase交易的工作方式有关.
在第一个示例中,您在执行事务的节点上有一个本地侦听器.这意味着您具有存储在本地缓存中的该节点的确切值.在第二个示例中,您具有节点的值,但本地没有该节点的实际侦听器.该值来自云功能本身,不存储在本地.因此,当您进行交易时,Firebase会立即尝试对该值进行"猜测",这始终null
是开始的.一旦从服务器听到该值不是null
,该事务将重试,服务器将告诉它新值是什么.然后,交易将重试.但是,由于您不处理null
案例而只是返回undefined
,因此取消了交易.
我认为你真的不需要为你想做的事情做一笔交易.您可以item
在不执行事务的情况下获取两个代码示例中的值.例如,以下是更新Cloud Functions示例的方法:
exports.receiveAndRemove = functions.database.ref('/dropbox/{entryId}').onWrite(function (event) {
if (!event.data.exists()) {
return;
}
let item = event.data.val();
let itemRef = event.data.adminRef;
console.log(`Item: ${JSON.stringify(item)} at ${event.data.key}`);
console.log(`Item ref: ${itemRef.toString()}`);
return itemRef.remove();
});