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

feat: add task to release unused db conns #1640

Merged
merged 9 commits into from
Dec 5, 2024

Conversation

taddes
Copy link
Contributor

@taddes taddes commented Dec 5, 2024

Description

By default, Deadpool releases unused connections pretty lazily, causing connections that may otherwise be available to be tied up unnecessarily. This could be part of what’s causing pods to run out of available connections to Spanner in certain cases. To resolve this, we should pursue a solution like the one described here, where we spawn a background task that periodically releases connections that haven’t been used within a given amount of time (this amount of time should be configurable in a setting).

To do this, we’ll need to make use of the Pool::retain method, which was introduced in deadpool 0.9.3 (we’re currently on version 0.5, so we’ll need to upgrade).

Testing

How should reviewers test?

Issue(s)

Closes SYNC-4542.

@taddes taddes self-assigned this Dec 5, 2024
@taddes taddes force-pushed the feat/add-task-to-release-unused-db-conns-SYNC-4542 branch from cb9ceb5 to 8f4a11b Compare December 5, 2024 01:55
@@ -78,6 +78,8 @@ pub struct Settings {
pub database_pool_connection_lifespan: Option<u32>,
/// Max time a connection should sit idle before being dropped.
pub database_pool_connection_max_idle: Option<u32>,
/// Interval for sweeper task releasing unused connections.
pub database_pool_sweeper_task_interval: Option<u32>,
Copy link
Member

Choose a reason for hiding this comment

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

Let's kill the Option, it's a bit of an anti pattern with a default of Some -- because there's no way to force it to a None (at least not from an environment variable) that I know of

Suggested change
pub database_pool_sweeper_task_interval: Option<u32>,
pub database_pool_sweeper_task_interval: u32,

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@pjenvey you ok with 30 s as a sweeper interval?

Copy link
Member

Choose a reason for hiding this comment

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

Yea, whatever works for autopush should be fine for syncstorage

Comment on lines 67 to 68
/// Interval for sweeper task releasing unused connections.
pub pool_max_idle: Option<u32>,
Copy link
Member

Choose a reason for hiding this comment

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

We already have a database_pool_connection_max_idle setting, let's use that instead -- the pool implementation uses it to timeout connections as it checks them out, but I believe the sweeper's going to do a better job of reducing the number than that code

Copy link
Contributor Author

@taddes taddes Dec 5, 2024

Choose a reason for hiding this comment

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

You bet @pjenvey , I wasn't 100% sure about reusing some of those settings so opted to just make a new one.

Copy link
Member

@pjenvey pjenvey Dec 5, 2024

Choose a reason for hiding this comment

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

I think we can kill it entirely after using the other setting?

@taddes taddes requested a review from pjenvey December 5, 2024 20:55
let pool = self.pool.clone();
rt::spawn(async move {
loop {
sweeper(&pool, Duration::from_secs(max_idle.into()));
Copy link
Member

Choose a reason for hiding this comment

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

in general, prefer constructing something like this Duration outside of the loop -- but it's a small, Copy type anyway so it doesn't really matter at all here

@taddes taddes merged commit c01021b into master Dec 5, 2024
9 checks passed
@taddes taddes deleted the feat/add-task-to-release-unused-db-conns-SYNC-4542 branch December 5, 2024 22:10
/// Spawn a task to periodically evict idle connections. Calls wrapper sweeper fn
/// to use pool.retain, retaining objects only if they are shorter in duration than
/// defined max_idle. Noop for mysql impl.
pub fn spawn_sweeper(&self, _interval: Duration) {
Copy link
Member

Choose a reason for hiding this comment

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

If this is a function that all implementations of DbPool should perform, we should add it to the DbPool trait (and move this to the impl DbPool block.

I wonder if we should rename this to spawn_maintenance (spawn_janitor?)

While we don't need to sweep for pool connections for SQL libs, folk may want to do other maintenance things like run vacuum or the like.

/// to use pool.retain, retaining objects only if they are shorter in duration than
/// defined max_idle. Noop for mysql impl.
pub fn spawn_sweeper(&self, _interval: Duration) {
sweeper()
Copy link
Member

Choose a reason for hiding this comment

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

I think we can drop this and make spawn_sweeper(..) the noop in MysqlDb.

/// to release the given connections.
/// See: https://docs.rs/deadpool/latest/deadpool/managed/struct.Pool.html#method.retain
/// Noop for mysql impl
fn sweeper() {}
Copy link
Member

Choose a reason for hiding this comment

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

Yeah, let's drop this. Less functions, less problems.

/// Spawn a task to periodically evict idle connections. Calls wrapper sweeper fn
/// to use pool.retain, retaining objects only if they are shorter in duration than
/// defined max_idle.
pub fn spawn_sweeper(&self, interval: Duration) {
Copy link
Member

Choose a reason for hiding this comment

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

If you do move this to the impl DbPool trait, you can keep the fn sweeper() as part of the general impl block.

@jrconlin
Copy link
Member

jrconlin commented Dec 5, 2024

Let's add a new trait method for spawn_sweeper (or rename it to spawn_maintenance) in DbPool. We're essentially requiring it for all DbPool implementations, so might as well make it official.

@taddes taddes changed the title Feat: add task to release unused db conns feat: add task to release unused db conns Dec 5, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants