minty
minty8mo ago

Middleware or request lifecycle hook to run after procedure?

Hi, I am using trpc context to create a database client for an incoming request. My understanding is this runs for every request, which is what I want. I want to be able to systematically close the databaase client at the end of any TRPC request. Is there any way of doing this? Perhaps with a middleware or request lifecycle hook? I couldn't find any documentation on it. This is the structure I want:
1. Request start
2. Context is created --> DB open
3. Procedure runs
4. DB is closed
1. Request start
2. Context is created --> DB open
3. Procedure runs
4. DB is closed
Thank you!
Solution:
is this sort of what you mean? ``` const withDb = middleware((opts) => { const db = getServerlessDBInstance();...
Jump to solution
11 Replies
Nick
Nick8mo ago
Yep just await next() into a variable, do your work, and then return the variable But generally with DBs you want to have a persistent pool, opening and closing connections is expensive, so maintaining a pool instance means there are always some open connections available
minty
minty8mo ago
I am using Neon (neon.tech) as my DB provider and they explicitly say to close it at the end of every request:
The Pool and Client objects must be connected, used, and closed within a single request handler. Don't create the objects outside a request handler; don't create them in one handler and try to reuse them in another; and to avoid exhausting available connections, don't forget to close them.
The Pool and Client objects must be connected, used, and closed within a single request handler. Don't create the objects outside a request handler; don't create them in one handler and try to reuse them in another; and to avoid exhausting available connections, don't forget to close them.
from here: https://neon.tech/docs/serverless/serverless-driver
Neon
Neon serverless driver - Neon Docs
The Neon serverless driver is a low-latency Postgres driver for JavaScript and TypeScript that allows you to query data from serverless and edge environments over HTTP or WebSockets in place of TCP. Y...
minty
minty8mo ago
Can you explain what you mean why the awaiting the next() variable? I would like the procedure to have access to the ctx.db, but not have to remember to close it Oh I think I see what you mean. Like the middleware would be:
openDB()

const result = await next()

closeDB()

return result
openDB()

const result = await next()

closeDB()

return result
is that what you mean?
Nick
Nick8mo ago
Fair enough then! Obviously their advice takes precedence 🙂 Yep! Middlewares are flexible 🙂
minty
minty8mo ago
got it, thank you! I will try that out
Nick
Nick8mo ago
You can add the DB in to the ctx by passing it to next() as well
minty
minty8mo ago
ahh perfect ok
Nick
Nick8mo ago
it will be merged, no pain needed from you
Solution
minty
minty8mo ago
is this sort of what you mean?
const withDb = middleware((opts) => {
const db = getServerlessDBInstance();

const result = opts.next({ ctx: { db } });

return result;
});
const withDb = middleware((opts) => {
const db = getServerlessDBInstance();

const result = opts.next({ ctx: { db } });

return result;
});
minty
minty8mo ago
(obviously I will add the db.end() as well)
Nick
Nick8mo ago
Exactly