Try another hacky approach for tearing down DBs after all tests

Max Brunsfeld and Nathan Sobo created

Co-Authored-By: Nathan Sobo <nathan@zed.dev>

Change summary

Cargo.lock               |  1 
crates/server/Cargo.toml |  1 
crates/server/src/db.rs  | 47 ++++++++++++++++++++++++++++-------------
3 files changed, 34 insertions(+), 15 deletions(-)

Detailed changes

Cargo.lock 🔗

@@ -5850,6 +5850,7 @@ dependencies = [
  "tide-compress",
  "time 0.2.25",
  "toml",
+ "util",
  "zed",
 ]
 

crates/server/Cargo.toml 🔗

@@ -61,6 +61,7 @@ gpui = { path = "../gpui" }
 zed = { path = "../zed", features = ["test-support"] }
 ctor = "0.1"
 env_logger = "0.8"
+util = { path = "../util" }
 
 lazy_static = "1.4"
 serde_json = { version = "1.0.64", features = ["preserve_order"] }

crates/server/src/db.rs 🔗

@@ -534,6 +534,7 @@ pub mod tests {
         Postgres,
     };
     use std::{mem, path::Path};
+    use util::ResultExt as _;
 
     pub struct TestDb {
         pub db: Option<Db>,
@@ -545,13 +546,31 @@ pub mod tests {
         static ref POOL: Mutex<Vec<TestDb>> = Default::default();
     }
 
-    #[ctor::dtor]
-    fn clear_pool() {
-        for db in POOL.lock().drain(..) {
-            db.teardown();
+    use std::os::raw::c_int;
+
+    extern "C" {
+        fn atexit(callback: extern "C" fn()) -> c_int;
+    }
+
+    #[ctor::ctor]
+    fn init() {
+        unsafe {
+            atexit(teardown_db_pool);
         }
     }
 
+    extern "C" fn teardown_db_pool() {
+        std::thread::spawn(|| {
+            block_on(async move {
+                for db in POOL.lock().drain(..) {
+                    db.teardown().await.log_err();
+                }
+            });
+        })
+        .join()
+        .log_err();
+    }
+
     impl TestDb {
         pub fn new() -> Self {
             let mut pool = POOL.lock();
@@ -606,22 +625,20 @@ pub mod tests {
             })
         }
 
-        fn teardown(mut self) {
+        async fn teardown(mut self) -> Result<()> {
             let db = self.db.take().unwrap();
-            block_on(async {
-                let query = "
+            let query = "
                     SELECT pg_terminate_backend(pg_stat_activity.pid)
                     FROM pg_stat_activity
                     WHERE pg_stat_activity.datname = '{}' AND pid <> pg_backend_pid();
                 ";
-                sqlx::query(query)
-                    .bind(&self.name)
-                    .execute(&db.pool)
-                    .await
-                    .unwrap();
-                db.pool.close().await;
-                Postgres::drop_database(&self.url).await.unwrap();
-            });
+            sqlx::query(query)
+                .bind(&self.name)
+                .execute(&db.pool)
+                .await?;
+            db.pool.close().await;
+            Postgres::drop_database(&self.url).await?;
+            Ok(())
         }
     }