First thing is to say that I have seen this question Sharing a pg-promise task across parts of an http request and read the answer. I'd like to revisit the question with some added complication.
I am working on a typescript graphql server on apollo-server-express
using a postgres database as the backend and pg-promise
as the database interface library. I have query resolvers using dataloaders using the pattern described here: https://github.com/graphql/dataloader#creating-a-new-dataloader-per-request.
All database access occurs via a single instance of pg-promise
as recommended e.g. https://github.com/vitaly-t/pg-promise-demo/blob/master/TypeScript/db/index.ts.
Like the original question, I am trying to find a good way to create a Task that can be incorporated into the dataloaders (or passed as a param when the dataloader is called) such that query resolvers operate within a single database connection. I don't know which resolvers will be called or in which order they will be called so I can't say that a certain resolver should create the task.
I've been trying to figure a way to use the graphql Context
to share the task as I am currently using the Context
to share the dataloaders object but as was noted, all calls in the task happen within a callback function so sharing the task via the Context
is out. Here's an example of how the context is setup:
/*
createLoaders() returns a new object of DataLoaders e.g.
{
users: new DataLoader(ids => getUsers(ids)),
tags: new DataLoader(ids => getTags(ids))
}
*/
import { createLoaders } from './dataloaders'
const server = new ApolloServer({
schema,
context: (): Promise<Context> => {
// create a connection here to inject into createLoaders?
const loaders = createLoaders()
return { loaders }
}
})
and an example in the Apollo docs of creating a db connection within the context: https://www.apollographql.com/docs/apollo-server/data/resolvers/#the-context-argument (note that they don't describe closing the connection anywhere).
context: async () => ({
db: await client.connect(),
})
// Resolver
(parent, args, context, info) => {
return context.db.query('SELECT * FROM table_name');
}
This may not be possible without using the connect
method, but its use for this type of operation is discouraged by the author of the libary. And the same problem arises that the connection needs to be returned to the pool when the query is finally resolved just before sending results back to the client.
Any help is appreciated! (and thanks to @vitaly-t for such strong work on pg-promise
)
Edit 1 @Daniel-Rearden your suggestion and linked gist ended up working. I will likely inspect incoming requests from within the plugin if always opening a task becomes an issue. Marking your answer correct!