Acknowledge channel notes and chat changes when views are active

Co-authored-by: Mikayla <mikayla@zed.dev>
This commit is contained in:
Max Brunsfeld 2023-10-03 17:40:10 -07:00
parent af09861f5c
commit 61e0289014
19 changed files with 478 additions and 209 deletions

View file

@ -432,7 +432,12 @@ impl Database {
channel_id: ChannelId,
user: UserId,
operations: &[proto::Operation],
) -> Result<(Vec<ConnectionId>, Vec<UserId>)> {
) -> Result<(
Vec<ConnectionId>,
Vec<UserId>,
i32,
Vec<proto::VectorClockEntry>,
)> {
self.transaction(move |tx| async move {
self.check_user_is_channel_member(channel_id, user, &*tx)
.await?;
@ -453,6 +458,7 @@ impl Database {
.collect::<Vec<_>>();
let mut channel_members;
let max_version;
if !operations.is_empty() {
let max_operation = operations
@ -460,6 +466,11 @@ impl Database {
.max_by_key(|op| (op.lamport_timestamp.as_ref(), op.replica_id.as_ref()))
.unwrap();
max_version = vec![proto::VectorClockEntry {
replica_id: *max_operation.replica_id.as_ref() as u32,
timestamp: *max_operation.lamport_timestamp.as_ref() as u32,
}];
// get current channel participants and save the max operation above
self.save_max_operation(
user,
@ -492,6 +503,7 @@ impl Database {
.await?;
} else {
channel_members = Vec::new();
max_version = Vec::new();
}
let mut connections = Vec::new();
@ -510,7 +522,7 @@ impl Database {
});
}
Ok((connections, channel_members))
Ok((connections, channel_members, buffer.epoch, max_version))
})
.await
}
@ -712,12 +724,12 @@ impl Database {
.await
}
pub async fn channels_with_changed_notes(
pub async fn unseen_channel_buffer_changes(
&self,
user_id: UserId,
channel_ids: &[ChannelId],
tx: &DatabaseTransaction,
) -> Result<HashSet<ChannelId>> {
) -> Result<Vec<proto::UnseenChannelBufferChange>> {
#[derive(Debug, Clone, Copy, EnumIter, DeriveColumn)]
enum QueryIds {
ChannelId,
@ -750,37 +762,45 @@ impl Database {
}
drop(rows);
let last_operations = self
.get_last_operations_for_buffers(channel_ids_by_buffer_id.keys().copied(), &*tx)
let latest_operations = self
.get_latest_operations_for_buffers(channel_ids_by_buffer_id.keys().copied(), &*tx)
.await?;
let mut channels_with_new_changes = HashSet::default();
for last_operation in last_operations {
if let Some(observed_edit) = observed_edits_by_buffer_id.get(&last_operation.buffer_id)
{
if observed_edit.epoch == last_operation.epoch
&& observed_edit.lamport_timestamp == last_operation.lamport_timestamp
&& observed_edit.replica_id == last_operation.replica_id
let mut changes = Vec::default();
for latest in latest_operations {
if let Some(observed) = observed_edits_by_buffer_id.get(&latest.buffer_id) {
if (
observed.epoch,
observed.lamport_timestamp,
observed.replica_id,
) >= (latest.epoch, latest.lamport_timestamp, latest.replica_id)
{
continue;
}
}
if let Some(channel_id) = channel_ids_by_buffer_id.get(&last_operation.buffer_id) {
channels_with_new_changes.insert(*channel_id);
if let Some(channel_id) = channel_ids_by_buffer_id.get(&latest.buffer_id) {
changes.push(proto::UnseenChannelBufferChange {
channel_id: channel_id.to_proto(),
epoch: latest.epoch as u64,
version: vec![proto::VectorClockEntry {
replica_id: latest.replica_id as u32,
timestamp: latest.lamport_timestamp as u32,
}],
});
}
}
Ok(channels_with_new_changes)
Ok(changes)
}
pub async fn get_last_operations_for_buffers(
pub async fn get_latest_operations_for_buffers(
&self,
channel_ids: impl IntoIterator<Item = BufferId>,
buffer_ids: impl IntoIterator<Item = BufferId>,
tx: &DatabaseTransaction,
) -> Result<Vec<buffer_operation::Model>> {
let mut values = String::new();
for id in channel_ids {
for id in buffer_ids {
if !values.is_empty() {
values.push_str(", ");
}
@ -795,13 +815,10 @@ impl Database {
r#"
SELECT
*
FROM (
FROM
(
SELECT
buffer_id,
epoch,
lamport_timestamp,
replica_id,
value,
*,
row_number() OVER (
PARTITION BY buffer_id
ORDER BY
@ -812,17 +829,17 @@ impl Database {
FROM buffer_operations
WHERE
buffer_id in ({values})
) AS operations
) AS last_operations
WHERE
row_number = 1
"#,
);
let stmt = Statement::from_string(self.pool.get_database_backend(), sql);
let operations = buffer_operation::Model::find_by_statement(stmt)
Ok(buffer_operation::Entity::find()
.from_raw_sql(stmt)
.all(&*tx)
.await?;
Ok(operations)
.await?)
}
}

View file

@ -463,20 +463,20 @@ impl Database {
}
let channel_ids = graph.channels.iter().map(|c| c.id).collect::<Vec<_>>();
let channels_with_changed_notes = self
.channels_with_changed_notes(user_id, &channel_ids, &*tx)
let channel_buffer_changes = self
.unseen_channel_buffer_changes(user_id, &channel_ids, &*tx)
.await?;
let channels_with_new_messages = self
.channels_with_new_messages(user_id, &channel_ids, &*tx)
let unseen_messages = self
.unseen_channel_messages(user_id, &channel_ids, &*tx)
.await?;
Ok(ChannelsForUser {
channels: graph,
channel_participants,
channels_with_admin_privileges,
channels_with_changed_notes,
channels_with_new_messages,
unseen_buffer_changes: channel_buffer_changes,
channel_messages: unseen_messages,
})
}

View file

@ -279,12 +279,12 @@ impl Database {
Ok(())
}
pub async fn channels_with_new_messages(
pub async fn unseen_channel_messages(
&self,
user_id: UserId,
channel_ids: &[ChannelId],
tx: &DatabaseTransaction,
) -> Result<collections::HashSet<ChannelId>> {
) -> Result<Vec<proto::UnseenChannelMessage>> {
let mut observed_messages_by_channel_id = HashMap::default();
let mut rows = observed_channel_messages::Entity::find()
.filter(observed_channel_messages::Column::UserId.eq(user_id))
@ -334,7 +334,7 @@ impl Database {
.all(&*tx)
.await?;
let mut channels_with_new_changes = HashSet::default();
let mut changes = Vec::new();
for last_message in last_messages {
if let Some(observed_message) =
observed_messages_by_channel_id.get(&last_message.channel_id)
@ -343,10 +343,13 @@ impl Database {
continue;
}
}
channels_with_new_changes.insert(last_message.channel_id);
changes.push(proto::UnseenChannelMessage {
channel_id: last_message.channel_id.to_proto(),
message_id: last_message.id.to_proto(),
});
}
Ok(channels_with_new_changes)
Ok(changes)
}
pub async fn remove_channel_message(