spin icon indicating copy to clipboard operation
spin copied to clipboard

Initialization Tasks (e.g. creating database / seeding data)

Open ThorstenHans opened this issue 2 months ago • 4 comments

Developers can use the --sqlite flag as part of spin up and provide SQL commands to perform common tasks like executing DDL and/or DML before the actual Spin App bootstraps. Although this is great and useful for some situations, there are currently limitations:

  • Only available for SQLite
  • Only affects the default database

Facing those limitations results in developers coming up with different patterns, layouts, scripts, or make targets to bootstrap databases before running their Spin App. I think we could improve Spin here and make it more holistic to provide a general purpose initialization stage.

From DX point of view I would love to have a unified experience to perform initialization logic. Although I had different potential solutions in my mind, I wanna share my personal favorite approach here:

Wouldn't it be possible to provide an additional macro and let developers "code" their initialization logic? I'm thinking about something like shown below. 👇🏻


#[initialize]
pub fn initialize() -> anyhow::Result<()> {
  // perform initialization logic
}

#[http_component]
pub fn handle_req(req: Request) -> anyhow::Result<impl IntoResponse> {
  Ok(Response::new(200,())
}

This would allow developers to use variables, and environment variables configured in their spin.toml and to run initialization logic - like database seeding, no matter which DBMS they use.

ThorstenHans avatar Apr 09 '24 07:04 ThorstenHans

Wasm itself already allows for this kind of initialization but there is still some missing toolchain support, i.e. I'm not sure if there is any way to run arbitrary init code in Rust.

lann avatar Apr 09 '24 13:04 lann

There is a fundamental difference between initialization code that should be executed at "deployment" time (i.e. executed once when you "start" the application) vs. code that should be executed on every request.

Which one are you talking about here?

radu-matei avatar Apr 09 '24 13:04 radu-matei

cf. https://github.com/fermyon/spin/issues/604

itowlson avatar Apr 09 '24 19:04 itowlson

There is a fundamental difference between initialization code that should be executed at "deployment" time (i.e. executed once when you "start" the application) vs. code that should be executed on every request.

That's a good point.

I was mainly thinking about database initialization / seeding here. Obviously, initialization code must be non-disruptive to work seamlessly when invoked as part of every application start.

I don't expect the fn decorated with #[initialize] being executed on every request.

Wouldn't it be possible to invoke the fn while interpreting the application manifest and bootstrapping things like triggers? That would make it run once per app instance.

Provisioning a database server with necessary configuration is something that I would consider as "out of scope" because that's deployment / infra related.

ThorstenHans avatar Apr 10 '24 10:04 ThorstenHans