design-patterns - 将多个服务器操作作为单个事务执行的设计模式
问题描述
假设您有一个 SaaS 应用程序并希望在用户注册时执行以下操作:
- 验证他们的姓名、电子邮件等。
- 为用户创建一个Stripe Customer 帐户。
- 为新的 Stripe 客户订阅现有的 Stripe 计划。
- 在您的数据库中创建一条包含 Stripe 信息的用户记录。
- 为用户创建一个新会话。
- 将用户重定向到您应用的仪表板。
理想情况下,您希望所有这些都发生在单个事务中,即如果第 4 步失败,您希望撤消第 2 步和第 3 步……您不希望没有数据库记录的悬空 Stripe 客户和订阅。
您会推荐哪些设计模式来使这种多步骤/多服务流程具有事务性?
对于上下文
我正在使用 Node 中的 ES6 Promises 实现这个多步骤过程——伪代码如下:
async function signup_user_for_trial(req, res) {
const {email, name, plan, password} = req.body
if (!isValidEmail(email)) {
throw new Error(...)
}
let customer = await createStripeCustomer(email)
let subscription = await createSubscription(customer, plan)
let user = await createDBUser(customer, name, email, password)
let session = await createSession(req, user)
return res.redirect('/dashboard')
}
解决方案
我想我要做的是建立一个表来负责引用事务的所有关键部分。在您的示例中,通过Create a Customer API Endpoint 创建客户的第 2 步将产生一个客户 ID,而通过Create a Subscription API Endpoint 附加计划的第 3 步将产生一个 Subscription ID。
我将在您的数据库中有两个表:一个代表您的用户相对于他们的 Stripe 客户 ID,另一个代表用户是否需要“回滚”。
通常,您总是会填充用户表。如果您的流程在某处中断,请在“回滚”表中添加一个带有用户 ID(或类似内容)的条目和/或指示您是否也应该回滚任何费用的条目。有一个 cron-job 定期检查这些条目以异步执行一些关键请求:
显然有很多方法可以做到这一点,但在我看来,这似乎是最简单的。
推荐阅读
- android - 类路径中的运行时 JAR 文件的版本为 1.4,比 API 版本 1.5 旧?
- scala - sbt 项目中的 Java Actor
- macos - git 说在我的 cd 中单击现有文件时会创建一个二进制文件
- html - 奇怪的网页渲染
- php - 不能用??在刀片模板中,Laravel
- python - 有没有办法用 python 对高于值和系列阈值(连续数字高于阈值)的数据点进行分类?
- apache-flink - Flink:在DataStream API的批处理模式下左连接相当于Dataset API?
- slack - Slack API:如何将 `users:read` 范围添加到机器人令牌
- java - 将值从 java 代码放入 application.properties
- html - Angular 从变量中读取 onblur 占位符值,而不是对其进行硬编码