spin
spin copied to clipboard
Initialization Tasks (e.g. creating database / seeding data)
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.
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.
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?
cf. https://github.com/fermyon/spin/issues/604
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.