Tying resources like DB connection to actor lifecycle

How might you recommend tying a resource like a DB connection to the actor lifecycle? The below is what I was thinking, but there are a couple of issues with the approach: 1. db conn not available in createState. not critical, but would be nice to be able to lookup and initialize some state based on the input or actor key 2. not sure how to cleanup the connection. in cloudflare's example they are tying the connection to each request's lifecycle, and using ctx.waitUntil (https://developers.cloudflare.com/workers/databases/third-party-integrations/planetscale/#3-use-hyperdrive-from-your-worker), but that doesn't quite map 1-1 w actor lifecycle. There isn't a way to hook into actor destruction/cleanup is there? Might not be possible - haven't looked deep but I'm not sure if there is even a way with raw CF durable objects
import { env } from 'cloudflare:workers';

export const myActor = actor({
onCreate: (c, opts) => {
console.log('onCreate');
},

createState: (c, opts) => {
// Won't have access to DB here as far as I can tell, right?
// throws error if try to access vars
const db = c.vars.db;

return {};
},

createVars: async (c) => {
const db = createConnection({ uri: env.HYPERDRIVE.connectionString, applicationName: `agent-${this.key.join(':')}` });

return { db };
},

actions: {
myAction: async (c) => {
const foo = await c.vars.db.query('xyz');
// ...etc
},
},
});
import { env } from 'cloudflare:workers';

export const myActor = actor({
onCreate: (c, opts) => {
console.log('onCreate');
},

createState: (c, opts) => {
// Won't have access to DB here as far as I can tell, right?
// throws error if try to access vars
const db = c.vars.db;

return {};
},

createVars: async (c) => {
const db = createConnection({ uri: env.HYPERDRIVE.connectionString, applicationName: `agent-${this.key.join(':')}` });

return { db };
},

actions: {
myAction: async (c) => {
const foo = await c.vars.db.query('xyz');
// ...etc
},
},
});
Cloudflare Docs
PlanetScale
PlanetScale is a MySQL-compatible platform that makes databases infinitely scalable, easier and safer to manage.
20 Replies
jog1t
jog1tβ€’4mo ago
summoning the master of the rivetkit, @Nathan we have a dedicated db lib that supports drizzle and plain sql only for sqllite (i think its currently undocumented)
jog1t
jog1tβ€’4mo ago
would be nice to be able to lookup and initialize some state based on the input or actor key
you can utilize input parameters for that: https://www.rivet.gg/docs/actors/input/
Rivet
Input Parameters - Rivet
Pass initialization data to actors when creating instances
Nathan
Nathanβ€’4mo ago
looks like this is for hyperdrive for postgres/mysql
jog1t
jog1tβ€’4mo ago
yep, we could technically support those too
Nathan
Nathanβ€’4mo ago
1. i'd have to look, but i think we could flip the order of the two. i think it makes sense to run createVars before everything else. 2. the function signature for createVars is createVars(c: ActorContext, ctx: { ctx: DurableObjectsState, env: unknown }). you can use ctx to access the raw DO state. that should do the trick? sounds like: - cloudflare example should include this by default since you need to interface with durableobjectsstate - add this to the cf workers docs updated the fn signature we don't need env anymore, though for #2 – also natively support ctx.runInBackground which calls waitUntil under the hood. that's undocumented atm, will fix.
marbemac
marbemacOPβ€’4mo ago
sry had to step away right after the original post yeah for #1 if createVars ran first, would solve. don't need anything specific for hyperdrive - it's really just a specific PG uri via an env var that can grab from import { env } from 'cloudflare:workers';. the key is just needing to tie the lifecycle of that connection to the actor somehow for #2, how does runInBackground interact with CF durable objects? like for this case of wanting to close the connection when the DO is shutdown, when would one call runInBackground? for a traditional request you know when you're ready to return the response and can call the waitUntil there to guarantee the connection is cleaned up (or in a finally) - I'm just not sure how to tie connection cleanup to DO lifecycle. CF discord might be better spot for this Q tbh, unless you happen to know πŸ™‚
Nathan
Nathanβ€’4mo ago
yeah for #1 if createVars ran first, would solve. don't need anything specific for hyperdrive - it's really just a specific PG uri via an env var that can grab from import { env } from 'cloudflare:workers';. the key is just needing to tie the lifecycle of that connection to the actor somehow
afaik, DO does not provide a way to detect if the DO stops natively. they've designed the entire system so they can shut off DOs at will when upgrading/migrating servers. lmk if you know otherwise.
for #2, how does runInBackground interact with CF durable objects? like for this case of wanting to close the connection when the DO is shutdown, when would one call runInBackground? for a traditional request you know when you're ready to return the response and can call the waitUntil there to guarantee the connection is cleaned up (or in a finally) - I'm just not sure how to tie connection cleanup to DO lifecycle. CF discord might be better spot for this Q tbh, unless you happen to know πŸ™‚
yep – i don't think waitUntil (nor runInBackground) is what you're looking for. it might be possible to just store hyperdrive as a global const. they have some funky v8 stuff that lets you share some variables between DOs
marbemac
marbemacOPβ€’4mo ago
yeahh kinda thinking might not be possible. at same time, not sure how much of an issue it really is to let the actor/do die without formally closing the db connection πŸ€”. i asked over here, we'll see if somebody responds -> https://discord.com/channels/595317990191398933/773219443911819284/1403519818140876893
marbemac
marbemacOPβ€’4mo ago
hyperdrive = in the clear πŸ‘
No description
Nathan
Nathanβ€’4mo ago
thx! can you send over a code snippet with what you end up with so i can adapt it for the docs?
marbemac
marbemacOPβ€’4mo ago
yeah for sure
marbemac
marbemacOPβ€’4mo ago
only other docs update so far as I go through my "rivet newbie" journey is on the studio side - maybe a note that if using vite server you gotta deal with cors there
No description
Nathan
Nathanβ€’4mo ago
@jog1t can you take care of this one?
jog1t
jog1tβ€’4mo ago
yes, thanks!
Nathan
Nathanβ€’4mo ago
https://app.graphite.dev/github/pr/rivet-gg/rivet/2843 a few prs going up relating to cf docs and going to cut v0.9.9 which cleans up accessing the driver & a few other things realted to this
Graphite
Graphite
The end to end developer platform.
Nathan
Nathanβ€’4mo ago
dropped v0.9.9
marbemac
marbemacOPβ€’4mo ago
awesome! will try it out tomorrow 0.9.9 working well!
i'd have to look, but i think we could flip the order of the two. i think it makes sense to run createVars before everything else.
on this one, I'm assuming this change has not been decided on yet and thus is not in 0.9.9 right?
Nathan
Nathanβ€’4mo ago
yep. it’ll happen but haven’t had time yet. it sounds like it’s not blocking correct?
marbemac
marbemacOPβ€’4mo ago
not blocking, all good! and we haven't committed to rivet quite yet, still evaluating, so def don't prioritize anything for lil old us πŸ˜…
Nathan
Nathanβ€’4mo ago
we'll get it done if you need it!

Did you find this page helpful?