Node.js Firebase实时数据库事务和云功能
我在Firebase实时数据库中有一个列表,结构如下:Node.js Firebase实时数据库事务和云功能,node.js,firebase,firebase-realtime-database,google-cloud-functions,Node.js,Firebase,Firebase Realtime Database,Google Cloud Functions,我在Firebase实时数据库中有一个列表,结构如下: list: { change: { rate: integer, last: Date }, lock: string, elements: { ... }, size: integer } 客户端只向列表中添加元素。 元素的子元素上的onCreate事件触发了一个云函数。它事务性地增加数据库中的list.size,然后对可能涉及删除全部或部分子元素的元素执行计算。 还有一个云函数是由元素的
list: {
change: {
rate: integer,
last: Date
},
lock: string,
elements: {
...
},
size: integer
}
客户端只向列表中添加元素。
元素的子元素上的onCreate
事件触发了一个云函数。它事务性地增加数据库中的list.size
,然后对可能涉及删除全部或部分子元素的元素执行计算。
还有一个云函数是由元素的子元素上的onDelete
事件触发的,该事件只在数据库中事务性地递减list.size
。
问题是计数器在一段时间后变得不准确。有时它会显示列表中的更多元素,有时会显示更少的元素。
以下是[调整后的]代码:
exports.element_add=functions.database.ref('/list/elements/{element}).onCreate(
(快照、上下文)=>{
常量元素=snapshot.ref.parent;
回报新的承诺(
(解决、拒绝)=>{
const start=new Date().getTime();
异步瀑布(
[
//读写到list.change
// ...
(下一步)=>{
//增量列表大小
_changeSize(elements.parent,+1,1,next)
},
//如果需要,获取锁并对列表元素进行计算
// ...
],
//最后
职能(e){
//松开锁
// ...
//处理错误
如果(e)
退货拒收(e);
解决();
}
);
});
});
exports.element_remove=functions.database.ref('/list/elements/{element}).onDelete(
(快照、上下文)=>{
常量元素=snapshot.ref.parent;
回报新的承诺(
功能(解析、拒绝){
_changeSize(elements.parent,-1,1,
职能(e){
如果(e)
退货拒收(e);
解决();
}
)
}
)
});
函数_changeSize(列表、增量、尝试、完成){
list.child('size')。事务(
//更新
(大小)=>{
如果(大小===null)
返回null;
返回大小+增量;
},
//最后
(e、提交、快照){
如果(e){
错误(`size transaction error:${e},1秒后重试`);
//再试一次
返回setTimeout(_changeSize,1000,list,delta,尝试+1,完成);
}
log(提交?`新列表大小为${snapshot.val()}`:'列表大小未更新');
//如果提交,则返回新大小
完成(空,已提交?snapshot.val():未定义);
},
//不要在本地申请
假的
);
}
除了上面的两个云函数外,没有其他实体使用list.size
。问题是为什么list.size
的值与list.elements
不同步
更新2020-02-26:显然,某些onCreate/onDelete事件被多次接收!我们观察到它们在云函数的实例之间传播了3次。这是正常行为还是我们做错了什么?您必须使用实时数据库 如下所示,用于递增:
exports.element_add = functions.database.ref('/list/elements/{element}').onCreate(
(snapshot, context) => {
const sizeRef = admin
.database()
.ref('/list/size');
return sizeRef
.transaction(current_value => {
return (current_value || 0) + 1;
});
});
exports.element_delete = functions.database.ref('/list/elements/{element}').onDelete(
(snapshot, context) => {
const sizeRef = admin
.database()
.ref('/list/size');
return sizeRef
.transaction(current_value => {
if (current_value > 0) {
return current_value - 1;
} else {
//Normally we should never reach this line...
return null;
}
});
});
并按以下方式递减:
exports.element_add = functions.database.ref('/list/elements/{element}').onCreate(
(snapshot, context) => {
const sizeRef = admin
.database()
.ref('/list/size');
return sizeRef
.transaction(current_value => {
return (current_value || 0) + 1;
});
});
exports.element_delete = functions.database.ref('/list/elements/{element}').onDelete(
(snapshot, context) => {
const sizeRef = admin
.database()
.ref('/list/size');
return sizeRef
.transaction(current_value => {
if (current_value > 0) {
return current_value - 1;
} else {
//Normally we should never reach this line...
return null;
}
});
});
你必须使用实时数据库 如下所示,用于递增:
exports.element_add = functions.database.ref('/list/elements/{element}').onCreate(
(snapshot, context) => {
const sizeRef = admin
.database()
.ref('/list/size');
return sizeRef
.transaction(current_value => {
return (current_value || 0) + 1;
});
});
exports.element_delete = functions.database.ref('/list/elements/{element}').onDelete(
(snapshot, context) => {
const sizeRef = admin
.database()
.ref('/list/size');
return sizeRef
.transaction(current_value => {
if (current_value > 0) {
return current_value - 1;
} else {
//Normally we should never reach this line...
return null;
}
});
});
并按以下方式递减:
exports.element_add = functions.database.ref('/list/elements/{element}').onCreate(
(snapshot, context) => {
const sizeRef = admin
.database()
.ref('/list/size');
return sizeRef
.transaction(current_value => {
return (current_value || 0) + 1;
});
});
exports.element_delete = functions.database.ref('/list/elements/{element}').onDelete(
(snapshot, context) => {
const sizeRef = admin
.database()
.ref('/list/size');
return sizeRef
.transaction(current_value => {
if (current_value > 0) {
return current_value - 1;
} else {
//Normally we should never reach this line...
return null;
}
});
});
您提到了一个实时数据库事务。您如何执行交易?为什么不使用标准事务机制()?事务实际上在
\u changeSize()
中使用。请看第一行,你提到了一个实时数据库事务。您如何执行交易?为什么不使用标准事务机制()?事务实际上在\u changeSize()
中使用。请看第一行。事务实际上在\u changeSize()
中使用。请看第一行。您是使用真正的实时数据库事务,还是使用另一个node.js
库来实现此“事务”?真正的事务。\u changeSize
接收到“list”ref,然后它在list.size
上启动一个事务。你能把\u changeSize
的确切代码添加到你的问题中吗?都在代码片段中。代码段中有3个函数<代码>\u changeSize()是最后一个。事务实际上在\u changeSize()
中使用。请看第一行。您是使用真正的实时数据库事务,还是使用另一个node.js
库来实现此“事务”?真正的事务。\u changeSize
接收到“list”ref,然后它在list.size
上启动一个事务。你能把\u changeSize
的确切代码添加到你的问题中吗?都在代码片段中。代码段中有3个函数<代码>\u changeSize()是最后一个。