Add database implementation of channel message change tracking

This commit is contained in:
Mikayla 2023-10-01 21:31:36 -07:00
parent e0ff7ba180
commit 51cf6a5ff3
No known key found for this signature in database
9 changed files with 339 additions and 19 deletions

View file

@ -787,16 +787,6 @@ impl Database {
}
}
fn max_assign<T: Ord>(max: &mut Option<T>, val: T) {
if let Some(max_val) = max {
if val > *max_val {
*max = Some(val);
}
} else {
*max = Some(val);
}
}
fn operation_to_storage(
operation: &proto::Operation,
buffer: &buffer::Model,

View file

@ -93,9 +93,13 @@ impl Database {
.stream(&*tx)
.await?;
let mut max_id = None;
let mut messages = Vec::new();
while let Some(row) = rows.next().await {
let row = row?;
dbg!(&max_id);
max_assign(&mut max_id, row.id);
let nonce = row.nonce.as_u64_pair();
messages.push(proto::ChannelMessage {
id: row.id.to_proto(),
@ -108,6 +112,55 @@ impl Database {
}),
});
}
drop(rows);
dbg!(&max_id);
if let Some(max_id) = max_id {
let has_older_message = dbg!(
observed_channel_messages::Entity::find()
.filter(
observed_channel_messages::Column::UserId
.eq(user_id)
.and(observed_channel_messages::Column::ChannelId.eq(channel_id))
.and(
observed_channel_messages::Column::ChannelMessageId.lt(max_id)
),
)
.one(&*tx)
.await
)?
.is_some();
if has_older_message {
observed_channel_messages::Entity::update(
observed_channel_messages::ActiveModel {
user_id: ActiveValue::Unchanged(user_id),
channel_id: ActiveValue::Unchanged(channel_id),
channel_message_id: ActiveValue::Set(max_id),
},
)
.exec(&*tx)
.await?;
} else {
observed_channel_messages::Entity::insert(
observed_channel_messages::ActiveModel {
user_id: ActiveValue::Set(user_id),
channel_id: ActiveValue::Set(channel_id),
channel_message_id: ActiveValue::Set(max_id),
},
)
.on_conflict(
OnConflict::columns([
observed_channel_messages::Column::UserId,
observed_channel_messages::Column::ChannelId,
])
.update_columns([observed_channel_messages::Column::ChannelMessageId])
.to_owned(),
)
.exec(&*tx)
.await?;
}
}
Ok(messages)
})
@ -130,11 +183,13 @@ impl Database {
let mut is_participant = false;
let mut participant_connection_ids = Vec::new();
let mut participant_user_ids = Vec::new();
while let Some(row) = rows.next().await {
let row = row?;
if row.user_id == user_id {
is_participant = true;
}
participant_user_ids.push(row.user_id);
participant_connection_ids.push(row.connection());
}
drop(rows);
@ -167,11 +222,77 @@ impl Database {
ConnectionId,
}
// Observe this message for all participants
observed_channel_messages::Entity::insert_many(participant_user_ids.iter().map(
|pariticpant_id| observed_channel_messages::ActiveModel {
user_id: ActiveValue::Set(*pariticpant_id),
channel_id: ActiveValue::Set(channel_id),
channel_message_id: ActiveValue::Set(message.last_insert_id),
},
))
.on_conflict(
OnConflict::columns([
observed_channel_messages::Column::ChannelId,
observed_channel_messages::Column::UserId,
])
.update_column(observed_channel_messages::Column::ChannelMessageId)
.to_owned(),
)
.exec(&*tx)
.await?;
Ok((message.last_insert_id, participant_connection_ids))
})
.await
}
#[cfg(test)]
pub async fn has_new_message_tx(&self, channel_id: ChannelId, user_id: UserId) -> Result<bool> {
self.transaction(|tx| async move { self.has_new_message(channel_id, user_id, &*tx).await })
.await
}
#[cfg(test)]
pub async fn dbg_print_messages(&self) -> Result<()> {
self.transaction(|tx| async move {
dbg!(observed_channel_messages::Entity::find()
.all(&*tx)
.await
.unwrap());
dbg!(channel_message::Entity::find().all(&*tx).await.unwrap());
Ok(())
})
.await
}
pub async fn has_new_message(
&self,
channel_id: ChannelId,
user_id: UserId,
tx: &DatabaseTransaction,
) -> Result<bool> {
self.check_user_is_channel_member(channel_id, user_id, &*tx)
.await?;
let latest_message_id = channel_message::Entity::find()
.filter(Condition::all().add(channel_message::Column::ChannelId.eq(channel_id)))
.order_by(channel_message::Column::SentAt, sea_query::Order::Desc)
.limit(1 as u64)
.one(&*tx)
.await?
.map(|model| model.id);
let last_message_read = observed_channel_messages::Entity::find()
.filter(observed_channel_messages::Column::ChannelId.eq(channel_id))
.filter(observed_channel_messages::Column::UserId.eq(user_id))
.one(&*tx)
.await?
.map(|model| model.channel_message_id);
Ok(dbg!(last_message_read) != dbg!(latest_message_id))
}
pub async fn remove_channel_message(
&self,
channel_id: ChannelId,