From 7e579f8d346d04bdcde32917cf296a9a7ef4f582 Mon Sep 17 00:00:00 2001
From: Jonathan de Jong <jonathan@automatia.nl>
Date: Mon, 19 Jul 2021 16:25:41 +0200
Subject: [PATCH] change to fraction-based approach

---
 src/database.rs                    | 19 +++++++++----------
 src/database/abstraction/sqlite.rs | 18 +++++++-----------
 2 files changed, 16 insertions(+), 21 deletions(-)

diff --git a/src/database.rs b/src/database.rs
index 82560db1e..f7c3d9d3f 100644
--- a/src/database.rs
+++ b/src/database.rs
@@ -53,8 +53,8 @@ pub struct Config {
     sqlite_wal_clean_second_interval: u32,
     #[serde(default = "default_sqlite_wal_clean_second_timeout")]
     sqlite_wal_clean_second_timeout: u32,
-    #[serde(default = "default_sqlite_spillover_reap_chunk")]
-    sqlite_spillover_reap_chunk: u32,
+    #[serde(default = "default_sqlite_spillover_reap_fraction")]
+    sqlite_spillover_reap_fraction: u32,
     #[serde(default = "default_sqlite_spillover_reap_interval_secs")]
     sqlite_spillover_reap_interval_secs: u32,
     #[serde(default = "default_max_request_size")]
@@ -125,12 +125,12 @@ fn default_sqlite_wal_clean_second_timeout() -> u32 {
     2
 }
 
-fn default_sqlite_spillover_reap_chunk() -> u32 {
-    5
+fn default_sqlite_spillover_reap_fraction() -> u32 {
+    2
 }
 
 fn default_sqlite_spillover_reap_interval_secs() -> u32 {
-    10
+    60
 }
 
 fn default_max_request_size() -> u32 {
@@ -558,10 +558,9 @@ pub fn flush_wal(&self) -> Result<()> {
 
     #[cfg(feature = "sqlite")]
     pub async fn start_spillover_reap_task(engine: Arc<Engine>, config: &Config) {
-        let chunk_size = match config.sqlite_spillover_reap_chunk {
-            0 => None, // zero means no chunking, reap everything
-            a @ _ => Some(a),
-        };
+        use std::convert::TryInto;
+
+        let fraction_factor = config.sqlite_spillover_reap_fraction.max(1).try_into().unwrap(/* We just converted it to be at least 1 */);
         let interval_secs = config.sqlite_spillover_reap_interval_secs as u64;
 
         let weak = Arc::downgrade(&engine);
@@ -577,7 +576,7 @@ pub async fn start_spillover_reap_task(engine: Arc<Engine>, config: &Config) {
                 i.tick().await;
 
                 if let Some(arc) = Weak::upgrade(&weak) {
-                    arc.reap_spillover(chunk_size);
+                    arc.reap_spillover_by_fraction(fraction_factor);
                 } else {
                     break;
                 }
diff --git a/src/database/abstraction/sqlite.rs b/src/database/abstraction/sqlite.rs
index ac92a45f9..e4acdbb56 100644
--- a/src/database/abstraction/sqlite.rs
+++ b/src/database/abstraction/sqlite.rs
@@ -9,6 +9,7 @@
 use std::{
     collections::BTreeMap,
     future::Future,
+    num::NonZeroU32,
     ops::Deref,
     path::{Path, PathBuf},
     pin::Pin,
@@ -241,19 +242,14 @@ pub fn flush_wal(self: &Arc<Self>) -> Result<()> {
             .map_err(Into::into)
     }
 
-    // Reaps (at most) X amount of connections if `amount` is Some.
-    // If none, reaps all currently idle connections.
-    pub fn reap_spillover(&self, amount: Option<u32>) {
+    // Reaps (at most) (.len() / `fraction`) (rounded down, min 1) connections.
+    pub fn reap_spillover_by_fraction(&self, fraction: NonZeroU32) {
         let mut reaped = 0;
 
-        if let Some(amount) = amount {
-            for _ in 0..amount {
-                if self.pool.spills.try_take().is_some() {
-                    reaped += 1;
-                }
-            }
-        } else {
-            while let Some(_) = self.pool.spills.try_take() {
+        let amount = ((self.pool.spills.1.len() as u32) / fraction).max(1);
+
+        for _ in 0..amount {
+            if self.pool.spills.try_take().is_some() {
                 reaped += 1;
             }
         }
-- 
GitLab