Remove random pauses to prevent the database from deadlocking
This commit is contained in:
parent
d97a8364ad
commit
d3c411677a
2 changed files with 62 additions and 54 deletions
|
@ -2131,31 +2131,35 @@ impl Database {
|
||||||
F: Send + Fn(TransactionHandle) -> Fut,
|
F: Send + Fn(TransactionHandle) -> Fut,
|
||||||
Fut: Send + Future<Output = Result<T>>,
|
Fut: Send + Future<Output = Result<T>>,
|
||||||
{
|
{
|
||||||
loop {
|
let body = async {
|
||||||
let (tx, result) = self.run(self.with_transaction(&f)).await?;
|
loop {
|
||||||
match result {
|
let (tx, result) = self.with_transaction(&f).await?;
|
||||||
Ok(result) => {
|
match result {
|
||||||
match self.run(async move { Ok(tx.commit().await?) }).await {
|
Ok(result) => {
|
||||||
Ok(()) => return Ok(result),
|
match tx.commit().await.map_err(Into::into) {
|
||||||
Err(error) => {
|
Ok(()) => return Ok(result),
|
||||||
if is_serialization_error(&error) {
|
Err(error) => {
|
||||||
// Retry (don't break the loop)
|
if is_serialization_error(&error) {
|
||||||
} else {
|
// Retry (don't break the loop)
|
||||||
return Err(error);
|
} else {
|
||||||
|
return Err(error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
Err(error) => {
|
||||||
Err(error) => {
|
tx.rollback().await?;
|
||||||
self.run(tx.rollback()).await?;
|
if is_serialization_error(&error) {
|
||||||
if is_serialization_error(&error) {
|
// Retry (don't break the loop)
|
||||||
// Retry (don't break the loop)
|
} else {
|
||||||
} else {
|
return Err(error);
|
||||||
return Err(error);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
|
self.run(body).await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn room_transaction<F, Fut, T>(&self, f: F) -> Result<RoomGuard<T>>
|
async fn room_transaction<F, Fut, T>(&self, f: F) -> Result<RoomGuard<T>>
|
||||||
|
@ -2163,39 +2167,43 @@ impl Database {
|
||||||
F: Send + Fn(TransactionHandle) -> Fut,
|
F: Send + Fn(TransactionHandle) -> Fut,
|
||||||
Fut: Send + Future<Output = Result<(RoomId, T)>>,
|
Fut: Send + Future<Output = Result<(RoomId, T)>>,
|
||||||
{
|
{
|
||||||
loop {
|
let body = async {
|
||||||
let (tx, result) = self.run(self.with_transaction(&f)).await?;
|
loop {
|
||||||
match result {
|
let (tx, result) = self.with_transaction(&f).await?;
|
||||||
Ok((room_id, data)) => {
|
match result {
|
||||||
let lock = self.rooms.entry(room_id).or_default().clone();
|
Ok((room_id, data)) => {
|
||||||
let _guard = lock.lock_owned().await;
|
let lock = self.rooms.entry(room_id).or_default().clone();
|
||||||
match self.run(async move { Ok(tx.commit().await?) }).await {
|
let _guard = lock.lock_owned().await;
|
||||||
Ok(()) => {
|
match tx.commit().await.map_err(Into::into) {
|
||||||
return Ok(RoomGuard {
|
Ok(()) => {
|
||||||
data,
|
return Ok(RoomGuard {
|
||||||
_guard,
|
data,
|
||||||
_not_send: PhantomData,
|
_guard,
|
||||||
});
|
_not_send: PhantomData,
|
||||||
}
|
});
|
||||||
Err(error) => {
|
}
|
||||||
if is_serialization_error(&error) {
|
Err(error) => {
|
||||||
// Retry (don't break the loop)
|
if is_serialization_error(&error) {
|
||||||
} else {
|
// Retry (don't break the loop)
|
||||||
return Err(error);
|
} else {
|
||||||
|
return Err(error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
Err(error) => {
|
||||||
Err(error) => {
|
tx.rollback().await?;
|
||||||
self.run(tx.rollback()).await?;
|
if is_serialization_error(&error) {
|
||||||
if is_serialization_error(&error) {
|
// Retry (don't break the loop)
|
||||||
// Retry (don't break the loop)
|
} else {
|
||||||
} else {
|
return Err(error);
|
||||||
return Err(error);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
|
self.run(body).await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn with_transaction<F, Fut, T>(&self, f: &F) -> Result<(DatabaseTransaction, Result<T>)>
|
async fn with_transaction<F, Fut, T>(&self, f: &F) -> Result<(DatabaseTransaction, Result<T>)>
|
||||||
|
@ -2233,13 +2241,7 @@ impl Database {
|
||||||
background.simulate_random_delay().await;
|
background.simulate_random_delay().await;
|
||||||
}
|
}
|
||||||
|
|
||||||
let result = self.runtime.as_ref().unwrap().block_on(future);
|
self.runtime.as_ref().unwrap().block_on(future)
|
||||||
|
|
||||||
if let Some(background) = self.background.as_ref() {
|
|
||||||
background.simulate_random_delay().await;
|
|
||||||
}
|
|
||||||
|
|
||||||
result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(test))]
|
#[cfg(not(test))]
|
||||||
|
|
|
@ -5672,7 +5672,13 @@ impl TestServer {
|
||||||
async fn start(background: Arc<executor::Background>) -> Self {
|
async fn start(background: Arc<executor::Background>) -> Self {
|
||||||
static NEXT_LIVE_KIT_SERVER_ID: AtomicUsize = AtomicUsize::new(0);
|
static NEXT_LIVE_KIT_SERVER_ID: AtomicUsize = AtomicUsize::new(0);
|
||||||
|
|
||||||
let test_db = TestDb::sqlite(background.clone());
|
let use_postgres = env::var("USE_POSTGRES").ok();
|
||||||
|
let use_postgres = use_postgres.as_deref();
|
||||||
|
let test_db = if use_postgres == Some("true") || use_postgres == Some("1") {
|
||||||
|
TestDb::postgres(background.clone())
|
||||||
|
} else {
|
||||||
|
TestDb::sqlite(background.clone())
|
||||||
|
};
|
||||||
let live_kit_server_id = NEXT_LIVE_KIT_SERVER_ID.fetch_add(1, SeqCst);
|
let live_kit_server_id = NEXT_LIVE_KIT_SERVER_ID.fetch_add(1, SeqCst);
|
||||||
let live_kit_server = live_kit_client::TestServer::create(
|
let live_kit_server = live_kit_client::TestServer::create(
|
||||||
format!("http://livekit.{}.test", live_kit_server_id),
|
format!("http://livekit.{}.test", live_kit_server_id),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue