node.js - 如何在 pg-promise 事务中包装 graphql 请求
问题描述
PG-Promise 提供了一个很好的安全交易包装器
db.tx(t => {
// Here you can use t to run any queries
// in a single transaction, on a single connection.
})
Apollo GraphQL Express 提供了一个 Express 中间件来处理 GraphQL 请求。它取决于一组预定义的“解析器”,它们解析请求的不同部分。这些解析器是从库中调用的,它们的结果放在一起形成响应。
我希望能够在 pg-promise 事务中包装 GraphQL 请求,该请求将获取多条数据或执行多个数据库操作(突变),以便具有基本的事务完整性。没有明显的方法可以做到这一点。
我想出的最好的想法是创建我自己的中间件以在 GraphQL 之前运行,这会向请求对象添加一个新的事务任务:
const bindTx = (req, res, next) => {
db.tx(async (t) => {
req = Object.assign(req, {getTransaction: () => t})
await next()
})
}
我的想法是这个中间件将确保下一个中间件在事务中运行。我把它放在 GraphQL 之前的 Express 链中:
app.use('/graphql', bodyParser.json(), bindTx, graphql)
然后,我的graphql
设置将添加到请求中的事务通过以下方式bindTx
传递给解析器context
:
const graphql = graphqlExpress((req) => {
const t = req.getTransaction()
return {
schema: makeExecutableSchema({
typeDefs,
resolvers
}),
context: {t}
}
}
最后,解析器可能如下所示:
getSomethingById(_, {somethingId}, context) {
context.t.one(
'select * from something where id = ${somethingId}',
{somethingId}
)
}
由于我了解 GraphQL 会按顺序运行解析器,并且它们可以返回一个必须在下一个解析器运行之前解析的承诺,我认为这会起作用。
这似乎会导致竞争条件,在大多数情况下它会产生错误Unhandled rejection Error: Querying against a released or lost connection.
,我相信这意味着当解析器运行并尝试查询事务时,事务已经关闭。
我根本不喜欢这种方法,实际上它似乎过于复杂,但我正在寻找某种方法来让我的 GraphQL 解析在事务中运行。虽然我目前正在使用 Express、Apollo 和 PG-Promise,但这些不是必需的,如果其他库可以解决问题的话。
有任何想法吗?
解决方案
推荐阅读
- python - python - 如何使python类型在期望其父类时将子类识别为有效类型?
- scala - 使用 shapeless 从案例类派生查询字符串参数
- java - 为什么 JMS 确认模式不能在 ibm mq 中广泛使用?
- xamarin.android - 在 Xamarin 中调用 JavaScript 函数
- gem5 - 修改gem5中的源代码并重建?
- vuejs2 - 使用 localhost:8080 注册新的 google.com recaptcha 站点引发错误
- kubernetes - Kubernetes 最佳实践 - 将任意数量的 pod 公开到互联网
- python-3.x - 我可以在没有 Flask 应用程序的情况下使用 Flask-Caching 吗?
- pandas - Subtracting two columns named in certain pattern
- php - MySQL data has wrong encoding when displaying using PHP