处理必须通过并进行"irreversible"更改的两个异步调用的最佳方法是什么?



我目前想知道这个问题,我有一个团队想要添加一个用户(所以在该团队的数据库中写入一个新用户(,我还想增加团队需要付费的用户数量(我使用条带订阅(。

async handleNewUser(user, teamId){
await addUserToTeamInDatabase(user, teamId)
await incrementSubscriberQuantityInStripe(teamId)
}

问题是,我该先做哪一个?我最近遇到了一个问题,添加了用户,但订阅人数没有增加。然而,如果我先反转它们并递增,然后写入数据库,而在最后一部分出现问题,则客户端会支付更多费用,但不会添加新成员。一种可能的方法是尝试捕获:

handleNewUser(user, teamId) {
let userAddedToDatabase = false
let userAddedInStripe = false
try {
await addUserToTeamInDatabase(user, teamId)
userAddedToDatabase = true
await incrementSubscriberQuantityInStripe(teamId)
userAddedToStripe = true
} catch (error) {
if (userAddedToDatabase && !userAddedInStripe) {
await removeUserFromTeamInDatabase()
}
}
}

因此,我将新用户写入数据库,然后调用stripe API。有没有更好的方法来处理这个问题,因为它感觉很笨拙。此外,是否有解决此问题的模式或名称?

我使用的是Firebase实时数据库。

谢谢大家!

您想要执行的是一个事务。在数据库中,事务是一组操作,如果其所有操作都成功,则该组操作是成功的。如果至少有一个操作失败,则不进行任何更改(取消或回滚所有其他操作(。

实时数据库支持交易!检查文件

如果两个操作都在同一个数据库中,通常会将它们捆绑在一个事务中,如果其中一个失败,数据库将恢复到初始状态。在您的案例中,您在不同的外部系统(DB&Stripe(中进行操作,因此您必须自己实现事务逻辑。

您可以通过检查catch子句中错误的来源来简化您的示例。然后你就可以摆脱这些旗帜了。类似这样的东西:

handleNewUser(user, teamId) {
try {
await addUserToTeamInDatabase(user, teamId)
await incrementSubscriberQuantityInStripe(teamId)
} catch (error) {
// If we fail to increment subscriber in Stripe,
// cancel transaction by removing user from DB
if (instanceof error StripeError) {
await removeUserFromTeamInDatabase(user, teamId)
}
// Re-throw error upstream
throw error;
}
}

我使用instanceof,但您可以更改条件逻辑以适合您的程序。

相关内容

  • 没有找到相关文章

最新更新