@@ -3,8 +3,9 @@ use anyhow::Context as _;
3
3
use chrono:: Utc ;
4
4
use native_tls:: { Certificate , TlsConnector } ;
5
5
use postgres_native_tls:: MakeTlsConnector ;
6
- use std:: sync:: { Arc , LazyLock , Mutex } ;
7
- use tokio:: sync:: { OwnedSemaphorePermit , Semaphore } ;
6
+ use serde_json;
7
+ use std:: sync:: { Arc , LazyLock } ;
8
+ use tokio:: sync:: { Mutex , OwnedSemaphorePermit , Semaphore } ;
8
9
use tokio_postgres:: Client as DbClient ;
9
10
10
11
pub mod issue_data;
@@ -37,8 +38,14 @@ pub struct PooledClient {
37
38
38
39
impl Drop for PooledClient {
39
40
fn drop ( & mut self ) {
40
- let mut clients = self . pool . lock ( ) . unwrap_or_else ( |e| e. into_inner ( ) ) ;
41
- clients. push ( self . client . take ( ) . unwrap ( ) ) ;
41
+ // We can't await in drop, so we need to spawn a task to handle async lock
42
+ if let Some ( client) = self . client . take ( ) {
43
+ let pool = self . pool . clone ( ) ;
44
+ tokio:: spawn ( async move {
45
+ let mut clients = pool. lock ( ) . await ;
46
+ clients. push ( client) ;
47
+ } ) ;
48
+ }
42
49
}
43
50
}
44
51
@@ -68,17 +75,21 @@ impl ClientPool {
68
75
pub async fn get ( & self ) -> PooledClient {
69
76
let permit = self . permits . clone ( ) . acquire_owned ( ) . await . unwrap ( ) ;
70
77
{
71
- let mut slots = self . connections . lock ( ) . unwrap_or_else ( |e| e . into_inner ( ) ) ;
78
+ let mut slots = self . connections . lock ( ) . await ;
72
79
// Pop connections until we hit a non-closed connection (or there are no
73
80
// "possibly open" connections left).
74
81
while let Some ( c) = slots. pop ( ) {
82
+ // drop the lock
83
+ drop ( slots) ;
75
84
if !c. is_closed ( ) && validate_connection ( & c) . await {
76
85
return PooledClient {
77
86
client : Some ( c) ,
78
87
permit,
79
88
pool : self . connections . clone ( ) ,
80
89
} ;
81
90
}
91
+ // re-lock
92
+ slots = self . connections . lock ( ) . await ;
82
93
}
83
94
}
84
95
0 commit comments