drizzle-team / drizzle-team/drizzle-orm

[FEATURE]: Callback on session acquisition + teardown

Open
#4,313 1 comment 0 reactions 0 assignees View on GitHub
driver/neon driver/supabase enhancement
Dominant language
TypeScript
Stars
35.8k
Forks
1.6k
Avg merge
2d 7h
Merged PRs (30d)
4

Description

### Feature hasn't been suggested before.

- [x] I have verified this feature I'm about to request hasn't been suggested before.

### Describe the enhancement you want to request

In order to implement RLS, you need to set the postgres role before doing any queries.

The Drizzle, Supabase, and Neon docs all suggest this pattern:
```ts
await db.transaction(tx => {
try {
await tx.execute(sql`
select set_config('request.jwt.claims', ..., TRUE);
`);
await tx....
} finally {
await tx.execute(sql`select set_config('request.jwt.claims', NULL, TRUE);`);
}
```

The problem is that a transaction is not always the right thing - for instance sometimes you need to make some DB calls during an http request handler, then call an LLM (which may take 3-10 seconds) and then make more DB calls - you shouldn't hold a transaction open for that long, as it will eat up your connections to the DB.

What is necessary is a way to execute the above SQL before and after drizzle creates/aquires a new session, so that roles and auth do not bleed across requests.

Now, you might be thinking, that's what stuff like the `pool.on('acquire', (poolClient) => ...)` hooks are for in `node-postgres`. The problem there is that when the acquire callback is fired, you have no idea what drizzle session that is associated with, so you don't have any way to reliably set things like jwt.claims.

I can think of two approaches to this:

### Callbacks on drizzle creation

Create a drizzle client on each incoming http connection - when you create the drizzle client, you include callbacks, e.g.
```ts
const authContext = getAuthContext(....);
const db = drizzle(pool, {
onSessionAcquired: (...) => {...stuff with authContext...},
onSessionReleased: (...) => {...}
});

```

Then you create a new db on every new http request, and still use a global persistent pool

### Fork a drizzle connection

There's a non-trivial amount of drizzle setup (dealing with schema, etc) when you call `drizzle(...)`, so perhaps a way to kind of fork a drizzle client, with specific setup/teardown:

Again, on every incoming http request
```ts
const authContext = getAuthContext(....);
const sessionDb = db.fork({
onSessionAcquired: (...) => {...stuff with authContext...},
onSessionReleased: (...) => {...}
});
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.