@@ -8,15 +8,15 @@ use sea_orm::{
88 DatabaseConnection , SqlxSqliteConnector , TransactionTrait ,
99} ;
1010use std:: sync:: Arc ;
11- use tokio:: sync:: Mutex ;
11+ use tokio:: sync:: { Mutex , Semaphore } ;
1212
1313// TODO: make these configurable via CLI.
1414
1515/// The timeout duration for database busy errors.
1616const BUSY_TIMEOUT_SECS : u64 = 5 ;
1717
1818/// The maximum number of connections in the database connection pool.
19- const MAX_CONNECTIONS : u32 = 10 ;
19+ const MAX_CONNECTIONS : u32 = 32 ;
2020
2121/// The minimum number of connections in the database connection pool.
2222const MIN_CONNECTIONS : u32 = 5 ;
@@ -36,6 +36,8 @@ pub struct Database {
3636 connection : DatabaseConnection ,
3737 /// A mutex to ensure that only one mutable transaction is active at a time.
3838 write_lock : Arc < Mutex < ( ) > > ,
39+ /// A semaphore to limit the number of concurrent read-only transactions.
40+ read_locks : Arc < Semaphore > ,
3941 /// The database metrics.
4042 metrics : DatabaseMetrics ,
4143 /// The temporary directory used for testing. We keep it here to ensure it lives as long as the
@@ -80,9 +82,13 @@ impl Database {
8082 . connect_with ( options)
8183 . await ?;
8284
85+ // We reserve one connection for write transactions.
86+ let read_connection_limit = max_connections as usize - 1 ;
87+
8388 Ok ( Self {
8489 connection : SqlxSqliteConnector :: from_sqlx_sqlite_pool ( sqlx_pool) ,
8590 write_lock : Arc :: new ( Mutex :: new ( ( ) ) ) ,
91+ read_locks : Arc :: new ( Semaphore :: new ( read_connection_limit) ) ,
8692 metrics : DatabaseMetrics :: default ( ) ,
8793 #[ cfg( feature = "test-utils" ) ]
8894 tmp_dir : None ,
@@ -111,7 +117,8 @@ impl DatabaseTransactionProvider for Database {
111117 /// Creates a new [`TX`] which can be used for read-only operations.
112118 async fn tx ( & self ) -> Result < TX , DatabaseError > {
113119 tracing:: trace!( target: "scroll::db" , "Creating new read-only transaction" ) ;
114- Ok ( TX :: new ( self . connection . clone ( ) . begin ( ) . await ?) )
120+ let permit = self . read_locks . clone ( ) . acquire_owned ( ) . await . unwrap ( ) ;
121+ Ok ( TX :: new ( self . connection . clone ( ) . begin ( ) . await ?, permit) )
115122 }
116123
117124 /// Creates a new [`TXMut`] which can be used for atomic read and write operations.
@@ -148,18 +155,6 @@ impl DatabaseConnectionProvider for Database {
148155 }
149156}
150157
151- impl From < DatabaseConnection > for Database {
152- fn from ( connection : DatabaseConnection ) -> Self {
153- Self {
154- connection,
155- write_lock : Arc :: new ( Mutex :: new ( ( ) ) ) ,
156- metrics : DatabaseMetrics :: default ( ) ,
157- #[ cfg( feature = "test-utils" ) ]
158- tmp_dir : None ,
159- }
160- }
161- }
162-
163158#[ cfg( test) ]
164159mod test {
165160 use super :: * ;
0 commit comments