Как вы можете обернуть запрос graphql в транзакцию pg-обещания - PullRequest
0 голосов
/ 27 апреля 2018

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. Это зависит от набора предопределенных «преобразователей», которые разрешают разные части запроса. Эти распознаватели вызываются из библиотеки, а их результаты объединяются в ответ.

Я бы хотел иметь возможность обернуть запрос GraphQL, который извлекает несколько фрагментов данных или выполняет несколько операций с базами данных (мутации), в транзакцию pg-обещания, чтобы обеспечить базовую целостность транзакции. Нет очевидного для меня способа сделать это.

Лучшая идея, которую я придумала, - это создать собственное промежуточное программное обеспечение для запуска до GraphQL, который добавляет новую задачу транзакции к объекту запроса:

const bindTx = (req, res, next) => {
    db.tx(async (t) => {
        req = Object.assign(req, {getTransaction: () => t})
        await next()
    })
}

Здесь я подумал, что это промежуточное программное обеспечение обеспечит запуск следующего промежуточного программного обеспечения внутри транзакции Я вставил это в цепочку Express перед GraphQL:

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, это не требования, если другие библиотеки могут решить эту проблему.

Есть идеи?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...