Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hook for cleaning up server? #6841

Closed
ghost opened this issue Sep 15, 2022 · 13 comments · Fixed by #8455
Closed

Hook for cleaning up server? #6841

ghost opened this issue Sep 15, 2022 · 13 comments · Fixed by #8455

Comments

@ghost
Copy link

ghost commented Sep 15, 2022

Describe the problem

Issue #1538 discusses about setting up external resources, but how do you clean them up?

Describe the proposed solution

The solution would be a cleanup() hook. Here is an example:

import DB from '$lib/db
const db = new DB(...)
const setup = db.connect() // returns a promise

/** @type {import('@sveltejs/kit').[Handle](https://kit.svelte.dev/docs/types#sveltejs-kit-handle)} */
export const handle = async ({ event, resolve }) => {
    await setup
    event.locals.db = db
    return await resolve(event)
}

export const cleanup = async () => {
    await db.disconnect()
}

Alternatives considered

Not Applicable

Importance

i cannot use SvelteKit without it

Additional Information

I chose the "i cannot use SvelteKit without it" because releasing resources is very important in any server application.

@Conduitry
Copy link
Member

I'm going to assume you're specifically talking about apps using the Node adapter.

Releasing resources when what? When the server process terminates? What sorts of resources are you concerned about not being automatically released already when the process terminates?

There's also currently not a reason (other than a catastrophic runtime error) that would result in the Node process from terminating besides it getting sent something like SIGINT, so you could also listen to that signal.

@ghost
Copy link
Author

ghost commented Sep 15, 2022

I meant to say that there should be a hook for releasing resources when the process is about to terminate via Ctrl-C or when using HMR. I am using the auto adapter that was configured by create-svelte.

@Conduitry
Copy link
Member

Again: What sorts of resources?

And are you deploying a production build anywhere? If you're just using npm run dev (or npm run preview) locally, then what adapter you have selected doesn't matter, because the adapter isn't used.

What does it mean to clean up resources when you're deploying to some sort of serverless environment? I don't see how this can be cross-platform. If you are targeting just Node, then you can use process.on('exit', ...), process.on('SIGINT', ...) etc as appropriate, but I don't see what the framework can provide.

@ghost
Copy link
Author

ghost commented Sep 15, 2022

The resources are anything that need to be awaited to close before the process is terminated. The example code shows a database connection (it could be knex, typeorm, etc.) with the connect and disconnect methods returning promises to be awaited by the hooks.

@ghost
Copy link
Author

ghost commented Sep 18, 2022

Never mind. I'm using a query builder that automatically disconnects when the process exits. 🤦‍♂️ However, some devs may need to manually close a database or Redis connection when the process exits (see the sqlite3 API for example), so this still may need discussion either way.

@Rich-Harris
Copy link
Member

For clarity, there's no opportunity to clean up resources when a module is invalidated during development. This is an issue with Vite: vitejs/vite#7887

@Rich-Harris Rich-Harris added this to the whenever milestone Sep 19, 2022
@tsmigiel
Copy link

I had a similar question about a prod sveltekit app. I am using adapter-node. I use mysql connection pools and on shutdown need to call pool.end() otherwise I have found the database can hang. The cases it would usually hang are definitely due to bugs in my app, but shutting down gracefully makes sure my bugs don't hang the database.

Before migrating to sveltekit I would wait for the http server to close before calling pool.end(). e.g.,
process.on('SIGINT', () => server.close(() => pool.end())); Using adapter-node, I have not figured out a way to achieve the same thing.

It might be safe for me to call pool.end() with out waiting for the server to close. The app is shutting down anyway, so a potential brief window of the server running but the pool being closed is probably not an issue.

@tsmigiel
Copy link

To follow up on my example. The solution I am currently using is to call process.on('exit', ...) and process.on('SIGINT', ...) to call my clean up code. I am still a beginner, so if this is a poor approach, I appreciate any feedback.

I wrote a few details here: https://stackoverflow.com/questions/74020726/how-to-shutdown-gracefully-in-sveltekit

@konstantinblaesi
Copy link

konstantinblaesi commented Nov 29, 2022

Using containerized sveltekit with adapter-node this works for me

Containerfile/Dockerfile (the end of it)

COPY --from=build /app/build build
ADD entry.js /app

EXPOSE 3000
ENTRYPOINT ["node", "/app/entry.js"]

entry.js

import {server as app} from "./build/index.js"

function shutdownGracefully() {
    console.log("Server doing graceful shutdown");
    app.server.close();
}

process.on("SIGINT", shutdownGracefully);
process.on("SIGTERM", shutdownGracefully);

podman run ... output after podman stop ...

Listening on 0.0.0.0:3000
Server doing graceful shutdown

@ghost
Copy link
Author

ghost commented Nov 29, 2022

@konstantinblaesi, although I appreciate your suggestion, Podman requires WSL2 (I have a Windows machine unfortunately 🤦‍♂️), which requires a paid license, and Docker does require a paid subscription and may also need WSL2 as well.

Although there are other options, with the knowledge gained from being an activist, I am probably speaking for other Svelte devs here by saying the following: with the current crises going on messing with the global economy, the most astute of us, including me, are trying to manage our money. Some devs cannot risk letting the price of one or more software licenses and subscriptions eating up their budgets, especially if the economy is poised to worsen in a few months.

That reason is why I think other devs and Sveltekit newcomers are looking for a built-in alternatives for an open source project, and not have to find out they need a paid subscription just to use the software they need while they are on a budget.

@konstantinblaesi
Copy link

konstantinblaesi commented Nov 29, 2022

@IRod22 sorry to disappoint you but your development setup is not my concern, there are free and non free options and also I don't make any proposals here what the node adapter should or should not implement . Make your choice / pick your poison I guess :D

I provide a solution that is usable today given someone wants to put their sveltekit app in a nodejs container.
I use podman on wsl2 fedora at work and podman on bare metal fedora at home. Me using wsl2 for work is just a consequence of my IT providing this by default and me not taking the time yet to mess around trying to change it to bare metal linux which I use on all my private machines.

Podman by the way is an open source tool developed by Red Hat (now IBM) and completely free, just like most of the tooling for making containers. Docker just made containers more accesible, improved the developer experience, provides more convenience. I don't use docker anywhere today, just open source / free tooling.

You might want to read some about operating system processes and signals because SIGINT and SIGTERM are such signals and two common ways an operating system might tell a process to shutdown gracefully. That's what my entry.js listens for and when containers are told to stop they send a SIGTERM to your process, if the application does not shutdown it gets killed (signal = SIGKILL) and has no chance to do cleanup, it just dies. When using docker/podman your process receives a SIGTERM and has 10 seconds to shutdown by default, after that it will be killed with SIGKILL.

If you don't need a container you may just use the entry.js for graceful shutodwn, but I assume you'd rather see this officially supported which makes sense to me, too.

@ghost
Copy link
Author

ghost commented Nov 29, 2022

@IRod22 sorry to disappoint you but your development setup is not my concern, . . .
I know that, @konstantinblaesi. I'm just stating a fact.

@dummdidumm
Copy link
Member

As Conduitry pointed out, there's no cross-platform way to achieve this, so using the native functionality of the environment you're in is the recommended solution. For Node that's the mentioned process.on('SIGINT', ...)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants