neondatabase / serverless

Connect to Neon PostgreSQL from serverless/worker/edge functions
https://www.npmjs.com/package/@neondatabase/serverless
MIT License
343 stars 13 forks source link

Suggestion: wake() function #36

Closed skybrian closed 1 year ago

skybrian commented 1 year ago

One way to wake a Neon database is with a dummy SQL statement like "select 1". However, this doesn't return until the database has started up, which may be a few seconds. A program can run it asynchronously and do other tasks, but there isn't any feedback about whether it successfully woke up the database, or how much longer it will take, until it finishes.

Therefore, it would nice for if the driver had a wake() function that sent a special API request to Neon that triggers database startup and returns immediately, without waiting until the database has started. If the call succeeds, the postcondition should be that either the database is ready, or it will be ready soon.

This would be useful even without any return value because you get immediate feedback about whether you've successfully connected to Neon. If wake() succeeds then it rules out network connectivity problems; in this way it's sort of like a ping.

But the return value could also include the database status, indicating whether the database is ready now. If it's still starting up, an estimate of how much time it will take to boot would be useful for setting the refresh interval on a "Loading..." screen. A program could also poll using wake() to get progress until the database becomes ready.

m-abdelwahab commented 1 year ago

this doesn't return until the database has started up, which may be a few seconds

@skybrian, we improved our cold start times, and they're now 1 second. We 're actively working on reducing it even further :)

If it's still starting up, an estimate of how much time it will take to boot would be useful for setting the refresh interval on a "Loading..." screen

Hmm, but why would you need a refresh interval? If you already have a loading screen, the loading time will include the time it takes for a compute endpoint to go from idle to active.

skybrian commented 1 year ago

It does seem faster now. Perhaps I won't need the loading screen.

Here is how it worked: ideally my little web app would load some data from the database at startup. This made startup take too long if the database is cold, so Deno Deploy would time out with a "bad gateway" error. This seemed rather user-unfriendly, so instead I wrote a "wake" function to run at startup. The result is logged but otherwise ignored since it might time out. Then I had it start loading the data on first request and respond with a web page with a loading screen and a meta-refresh. By the time it refreshes, the data is usually loaded.

It's not clear to me what restrictions Deno Deploy might have on network access outside handling a request. So far I haven't noticed a problem with that.

(This is all just prototyping. I haven't used Deno Deploy or Neon before.)

m-abdelwahab commented 1 year ago

This made startup take too long if the database is cold, so Deno Deploy would time out with a "bad gateway" error.

@skybrian Did this error occur when using the Serverless Driver or were you using a different one?

skybrian commented 1 year ago

I've always been using the @neondatabase/serverless driver, but on Deno rather than node, so this is an unusual configuration. Based on the file history I switched to the fetch-based API a couple weeks ago.

I'm guessing Deno Deploy may have changed too. At any rate, it starts up faster now:

data: 1: startup
data: 1.1 startup: wake
data: 1.1.1 wake at 1144 ms: database is ready
data: 2: load counters
data: 2.1 load counters: sent {"id":"accordions","symbol":"πŸͺ—","count":"227"}
data: 2.2 load counters: sent {"id":"apples","symbol":"🍎","count":"150"}
data: 2.3 load counters: sent {"id":"cherries","symbol":"πŸ’","count":"106"}
data: 2.4 load counters: sent {"id":"cows","symbol":"πŸ„","count":"463"}
data: 2.5 load counters: sent {"id":"ducks","symbol":"πŸ¦†","count":"111"}
data: 2.6 load counters at 82 ms: 5 rows
data: 1.2 startup: 1226 ms
data: 3: GET /
data: 3.1 GET /: 8 ms
data: 4: GET /log
data: 4.1 GET /log: 2 ms
jawj commented 1 year ago

@skybrian Are you still getting bad gateway errors, or can we close this?

skybrian commented 1 year ago

I'm not getting bad gateway errors. I left in my loading screen, but it's only up for one second (typically) on cold start, which I think is fine. It shows the user that they reached the web server.

So, I'm good. A wake() function might still be useful for debugging network issues, though? Similarly to how ping is useful.

jawj commented 1 year ago

OK, thanks. We'll bear this idea in mind, but for now I'll close the issue.