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

Upgrade hasql-pool #2391

Closed
wants to merge 13 commits into from
Closed

Upgrade hasql-pool #2391

wants to merge 13 commits into from

Conversation

robx
Copy link
Contributor

@robx robx commented Jul 27, 2022

Preparatory work for #2348, as discussed with @steve-chavez.

This loses the db-pool-timeout config option (and timing out of idle connections at all), and fixes #2401.

test/io/test_io.py Outdated Show resolved Hide resolved
src/PostgREST/AppState.hs Outdated Show resolved Hide resolved
Comment on lines +225 to +238
toJSON SQL.PoolIsReleasedUsageError = JSON.object [
"code" .= InternalErrorCode00,
"message" .= ("Use of released pool" :: Text),
"details" .= JSON.Null,
"hint" .= JSON.Null]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible for the user to get this error? AIUI, on usePool we try to recover from PoolIsReleasedUsageError immediately.

If it's possible, perhaps this momentary error should include a "Retrying.." message and a 503 status to clarify it's temporary.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not expected to be visible to the user except during shutdown, so not temporary in that sense.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. In that case maybe we should a have more user-facing error message, like:

Suggested change
toJSON SQL.PoolIsReleasedUsageError = JSON.object [
"code" .= InternalErrorCode00,
"message" .= ("Use of released pool" :: Text),
"details" .= JSON.Null,
"hint" .= JSON.Null]
toJSON SQL.PoolIsReleasedUsageError = JSON.object [
"code" .= InternalErrorCode00,
"message" .= ("The database connection pool is released. Shutting down.." :: Text),
"details" .= JSON.Null,
"hint" .= JSON.Null]

@robx
Copy link
Contributor Author

robx commented Aug 8, 2022

@steve-chavez I believe I've addressed the review comments, could you have another look?


-- | Flush the connection pool so that any future use of the pool will
-- use connections freshly established after this call. In-use
-- connections aren't affected, they just won't be reused anymore.
Copy link
Contributor Author

@robx robx Aug 8, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's one issue with the way we replace pools, in that there's a timespan where two pools are around (the old one with the in-process requests, and the new empty one). Until all the old requests are done, it's possible to exceed the configured pool size.

I tend feel it's ok to accept this while fixing the issue this addresses otherwise, and keep it in mind as something to be fixed down the line, but I can't really judge that.

To address this properly would have to happen in the pooling library. (Since hasql-pool is pretty small and I'm a bit doubtful of getting our changes upstreamed anytime soon, I'd probably inline Hasql.Pool, fix this for us, and file PRs upstream independently.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've implemented this as a patch to hasql-pool here nikita-volkov/hasql-pool#16.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to be clear, does nikita-volkov/hasql-pool#16 prevent exceeding the configured pool size?

Copy link
Contributor Author

@robx robx Aug 8, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to be clear, does nikita-volkov/hasql-pool#16 prevent exceeding the configured pool size?

Yes (well unless there's a bug in the PR).

@steve-chavez
Copy link
Member

Q: With the new flushPool, do see any performance impact in comparison to the old releasePool?

@robx
Copy link
Contributor Author

robx commented Aug 8, 2022

Q: With the new flushPool, do see any performance impact in comparison to the old releasePool?

I don't expect a meaningful performance impact for flushPool. The extra cost should be just looking up an IORef.

There's more likely to be performance regressions lurking in the hasql-pool rewrite, though the new version is simple enough that I don't expect anything there either. (The current hasql-pool version relies on an old resource-pool release, which uses STM just the same as the new hasql-pool, so I don't see any reason for new overhead as compared to the old version. Judging by the recent rewrite of resource-pool with non-STM for "better throughput and latency" there might be some room for improvement though.)

@steve-chavez
Copy link
Member

@robx I think this should be good to merge. Or should we wait on closing nikita-volkov/hasql-pool#16 or #2422?

@robx
Copy link
Contributor Author

robx commented Aug 24, 2022

@robx I think this should be good to merge. Or should we wait on closing nikita-volkov/hasql-pool#16 or #2422?

I think it's time to fork (not just for this issue but those other hasql issues too). Here's a clone of nikita-volkov/hasql-pool#16: PostgREST/hasql-pool#1.

…tgREST#2401)

This version of hasql-pool is a simplified rewrite that doesn't use
the resource-pool package. The major API changes are that idle
connections are no longer timed out (and the corresponding setting
is gone), and that `release` makes the pool unusable, where it used
to remain usable and only flushed idle connections.

- This change removes the db-pool-timeout option, since new
  hasql-pool doesn't provide timing out of idle connections.
  Given that we were typically running with very high
  timeout settings, I don't anticipate the lack of timeout
  to introduce new issues, though we might want to consider
  introducing some retry-logic down the line when we
  encounter connection failures.
- To recover the ability to flush idle connections, we add a
  somewhat painful pool wrapper that allows replacing the
  pool. This fixes PostgREST#2401 by ensuring that flushing the pool
  also prevents any active connections from being reused in
  the future.
The original test no longer makes sense since connections don't
timeout. To somehow test that new connections have the settings,
convert it to flush the pool instead.
@robx
Copy link
Contributor Author

robx commented Aug 29, 2022

Closing in favour of #2454.

@robx robx closed this Aug 29, 2022
@robx robx deleted the upgrade-pool branch August 29, 2022 15:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

Database connections can outlive SIGUSR1 reconfiguration
2 participants