Firebase 事务不会在失败时重复
Firebase transaction is not repeating on failure
更新:
这是我收到的 console.error(err)
消息:
Error: 6 ALREADY_EXISTS: Document already exists: projects/projectOne-e3999/databases/(default)/documents/storage/AAAAAAAAAA1111111111
我明白为什么会出现错误。因为并行事务 运行ning 执行事务的 else
部分速度更快。因此返回错误的事务不必创建而是更新文档。如果交易重新运行就足够了。但它并没有说明 Transactions are committed once 'updateFunction' resolves and attempted up to five times on failure
.
这就是问题的重点。当文档已经存在时,我如何防止交易失败,因为它是并行创建的,或者如何重新运行交易?
原题:
我有一个云函数,每当创建另一个集合中的文档时,它就会更新另一个文档。由于可以并行创建多个文档,所有这些文档都访问同一个文档,这将 运行 作为事务处理,保证了幂等性。
函数的结构如下所示。问题是第一次写入(因此创建了存储文档)。正如我所说,可以并行创建两个文档。但是现在事务读取了一个不存在的文档并尝试创建它,但是由于另一个事务(并行 运行ning 一个)已经创建了该文档,事务失败了。 (我一开始就不明白,因为我认为交易会在执行时阻止所有访问)
这根本不是问题,但它不会重试(尽管它声明最多会自动重试 5 次)。我认为这与我的异步函数的 try & catch 块有关。
如果重试,它将检测到文档存在并自动更新现有文档。
让我们简单点。此交易绝不能失败。如果没有可能的自动恢复方式,它会使数据库不一致。
.onCreate(async (snapshot, context) => {
//Handle idempotence
const eventId = context.eventId;
try {
const process = await shouldProcess(eventId)
if (!process) {
return null
}
const storageDoc = admin.firestore().doc(`storage/${snapshot.id}`)
await admin.firestore().runTransaction(async t => {
const storageDbDoc = await storageDoc.get()
const dataDb = storageDbDoc.data()
if (dataDb) {
//For sake of testing just rewrite it
t.update(storageDoc, dataDb )
} else {
//Create new
const storage = createStorageDoc()
t.create(storageDoc, storage )
}
})
return markProcessed(eventId)
} catch (err) {
console.error(`Execution of ${eventId} failed: ${err}`)
throw new Error(`Transaction failed.`);
}
您的事务坚持能够创建一个新文档:
t.create(storageDoc, storage)
由于create()在文档已经存在的条件下失败,整个交易就失败了,无法恢复。
如果您的交易必须能够恢复,您应该在尝试写入之前检查该文档是否存在,并决定在这种情况下您想要做什么。
更新:
这是我收到的 console.error(err)
消息:
Error: 6 ALREADY_EXISTS: Document already exists: projects/projectOne-e3999/databases/(default)/documents/storage/AAAAAAAAAA1111111111
我明白为什么会出现错误。因为并行事务 运行ning 执行事务的 else
部分速度更快。因此返回错误的事务不必创建而是更新文档。如果交易重新运行就足够了。但它并没有说明 Transactions are committed once 'updateFunction' resolves and attempted up to five times on failure
.
这就是问题的重点。当文档已经存在时,我如何防止交易失败,因为它是并行创建的,或者如何重新运行交易?
原题:
我有一个云函数,每当创建另一个集合中的文档时,它就会更新另一个文档。由于可以并行创建多个文档,所有这些文档都访问同一个文档,这将 运行 作为事务处理,保证了幂等性。
函数的结构如下所示。问题是第一次写入(因此创建了存储文档)。正如我所说,可以并行创建两个文档。但是现在事务读取了一个不存在的文档并尝试创建它,但是由于另一个事务(并行 运行ning 一个)已经创建了该文档,事务失败了。 (我一开始就不明白,因为我认为交易会在执行时阻止所有访问)
这根本不是问题,但它不会重试(尽管它声明最多会自动重试 5 次)。我认为这与我的异步函数的 try & catch 块有关。
如果重试,它将检测到文档存在并自动更新现有文档。
让我们简单点。此交易绝不能失败。如果没有可能的自动恢复方式,它会使数据库不一致。
.onCreate(async (snapshot, context) => {
//Handle idempotence
const eventId = context.eventId;
try {
const process = await shouldProcess(eventId)
if (!process) {
return null
}
const storageDoc = admin.firestore().doc(`storage/${snapshot.id}`)
await admin.firestore().runTransaction(async t => {
const storageDbDoc = await storageDoc.get()
const dataDb = storageDbDoc.data()
if (dataDb) {
//For sake of testing just rewrite it
t.update(storageDoc, dataDb )
} else {
//Create new
const storage = createStorageDoc()
t.create(storageDoc, storage )
}
})
return markProcessed(eventId)
} catch (err) {
console.error(`Execution of ${eventId} failed: ${err}`)
throw new Error(`Transaction failed.`);
}
您的事务坚持能够创建一个新文档:
t.create(storageDoc, storage)
由于create()在文档已经存在的条件下失败,整个交易就失败了,无法恢复。
如果您的交易必须能够恢复,您应该在尝试写入之前检查该文档是否存在,并决定在这种情况下您想要做什么。