chore: prevent hot loops in collab updates stream

This commit is contained in:
Bartosz Sypytkowski 2024-10-29 07:31:57 +01:00
parent 3ad2c3dacb
commit 961c482995
2 changed files with 38 additions and 29 deletions

View File

@ -121,9 +121,14 @@ impl CollabRedisStream {
let batch: CollabStreamUpdateBatch = conn
.xread_options(&[&stream_key], &[&last_id], &read_options)
.await?;
for (message_id, update) in batch.updates {
since = since.max(message_id);
yield (message_id, update);
if batch.updates.is_empty() {
tokio::time::sleep(Duration::from_millis(1000)).await;
} else {
for (message_id, update) in batch.updates {
since = since.max(message_id);
yield (message_id, update);
}
}
}
}
@ -146,9 +151,13 @@ impl CollabRedisStream {
let batch: AwarenessStreamUpdateBatch = conn
.xread_options(&[&stream_key], &[&last_id], &read_options)
.await?;
for (message_id, update) in batch.updates {
since = since.max(message_id);
yield update;
if batch.updates.is_empty() {
tokio::time::sleep(Duration::from_millis(1000)).await;
} else {
for (message_id, update) in batch.updates {
since = since.max(message_id);
yield update;
}
}
}
}
@ -157,28 +166,27 @@ impl CollabRedisStream {
pub async fn prune_stream(
&self,
stream_key: &str,
message_id: MessageId,
mut message_id: MessageId,
) -> Result<usize, StreamError> {
let mut conn = self.connection_manager.clone();
let value = conn.xrange(stream_key, "-", message_id.to_string()).await?;
let value = StreamRangeReply::from_owned_redis_value(value)?;
let msg_ids: Vec<_> = value
.ids
.into_iter()
.map(|stream_id| stream_id.id)
.collect();
if !msg_ids.is_empty() {
let count: usize = conn.xdel(stream_key, &msg_ids).await?;
drop(conn);
tracing::debug!(
"Pruned redis stream `{}` <= `{}` ({} objects)",
stream_key,
message_id,
count
);
Ok(count)
} else {
Ok(0)
}
// we want to delete everything <= message_id
message_id.sequence_number += 1;
let value = conn
.send_packed_command(
redis::cmd("XTRIM")
.arg(stream_key)
.arg("MINID")
.arg(format!("{}", message_id)),
)
.await?;
let count = usize::from_redis_value(&value)?;
drop(conn);
tracing::info!(
"pruned redis stream `{}` <= `{}` ({} objects)",
stream_key,
message_id,
count
);
Ok(count)
}
}

View File

@ -29,7 +29,7 @@ use futures::{pin_mut, Sink, Stream};
use futures_util::{SinkExt, StreamExt};
use std::sync::atomic::{AtomicU32, Ordering};
use std::sync::Arc;
use std::time::{Duration, Instant};
use std::time::{Duration, Instant, SystemTime};
use tokio::time::MissedTickBehavior;
use tokio_util::sync::CancellationToken;
use tracing::{error, info, trace};
@ -1070,8 +1070,9 @@ impl CollabPersister {
);
// 3. finally we can drop Redis messages
let now = SystemTime::UNIX_EPOCH.elapsed().unwrap().as_millis();
let msg_id = MessageId {
timestamp_ms: message_id.timestamp_ms - self.prune_grace_period.as_millis() as u64,
timestamp_ms: (now - self.prune_grace_period.as_millis()) as u64,
sequence_number: 0,
};
let stream_key = CollabStreamUpdate::stream_key(&self.workspace_id, &self.object_id);