Make notification db representation more flexible
This commit is contained in:
parent
fed3ffb681
commit
3241128840
17 changed files with 197 additions and 175 deletions
|
@ -81,3 +81,4 @@ id_type!(UserId);
|
|||
id_type!(ChannelBufferCollaboratorId);
|
||||
id_type!(FlagId);
|
||||
id_type!(NotificationId);
|
||||
id_type!(NotificationKindId);
|
||||
|
|
|
@ -165,18 +165,18 @@ impl Database {
|
|||
.exec_without_returning(&*tx)
|
||||
.await?;
|
||||
|
||||
if rows_affected == 1 {
|
||||
self.create_notification(
|
||||
receiver_id,
|
||||
rpc::Notification::ContactRequest {
|
||||
requester_id: sender_id.to_proto(),
|
||||
},
|
||||
&*tx,
|
||||
)
|
||||
.await
|
||||
} else {
|
||||
Err(anyhow!("contact already requested"))?
|
||||
if rows_affected == 0 {
|
||||
Err(anyhow!("contact already requested"))?;
|
||||
}
|
||||
|
||||
self.create_notification(
|
||||
receiver_id,
|
||||
rpc::Notification::ContactRequest {
|
||||
actor_id: sender_id.to_proto(),
|
||||
},
|
||||
&*tx,
|
||||
)
|
||||
.await
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
@ -260,7 +260,7 @@ impl Database {
|
|||
responder_id: UserId,
|
||||
requester_id: UserId,
|
||||
accept: bool,
|
||||
) -> Result<()> {
|
||||
) -> Result<proto::Notification> {
|
||||
self.transaction(|tx| async move {
|
||||
let (id_a, id_b, a_to_b) = if responder_id < requester_id {
|
||||
(responder_id, requester_id, false)
|
||||
|
@ -298,11 +298,18 @@ impl Database {
|
|||
result.rows_affected
|
||||
};
|
||||
|
||||
if rows_affected == 1 {
|
||||
Ok(())
|
||||
} else {
|
||||
if rows_affected == 0 {
|
||||
Err(anyhow!("no such contact request"))?
|
||||
}
|
||||
|
||||
self.create_notification(
|
||||
requester_id,
|
||||
rpc::Notification::ContactRequestAccepted {
|
||||
actor_id: responder_id.to_proto(),
|
||||
},
|
||||
&*tx,
|
||||
)
|
||||
.await
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
|
|
@ -1,21 +1,25 @@
|
|||
use super::*;
|
||||
use rpc::{Notification, NotificationKind};
|
||||
use rpc::Notification;
|
||||
|
||||
impl Database {
|
||||
pub async fn ensure_notification_kinds(&self) -> Result<()> {
|
||||
self.transaction(|tx| async move {
|
||||
notification_kind::Entity::insert_many(NotificationKind::all().map(|kind| {
|
||||
notification_kind::ActiveModel {
|
||||
id: ActiveValue::Set(kind as i32),
|
||||
name: ActiveValue::Set(kind.to_string()),
|
||||
}
|
||||
}))
|
||||
.on_conflict(OnConflict::new().do_nothing().to_owned())
|
||||
.exec(&*tx)
|
||||
.await?;
|
||||
Ok(())
|
||||
})
|
||||
.await
|
||||
pub async fn initialize_notification_enum(&mut self) -> Result<()> {
|
||||
notification_kind::Entity::insert_many(Notification::all_kinds().iter().map(|kind| {
|
||||
notification_kind::ActiveModel {
|
||||
name: ActiveValue::Set(kind.to_string()),
|
||||
..Default::default()
|
||||
}
|
||||
}))
|
||||
.on_conflict(OnConflict::new().do_nothing().to_owned())
|
||||
.exec_without_returning(&self.pool)
|
||||
.await?;
|
||||
|
||||
let mut rows = notification_kind::Entity::find().stream(&self.pool).await?;
|
||||
while let Some(row) = rows.next().await {
|
||||
let row = row?;
|
||||
self.notification_kinds_by_name.insert(row.name, row.id);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn get_notifications(
|
||||
|
@ -33,14 +37,16 @@ impl Database {
|
|||
.await?;
|
||||
while let Some(row) = rows.next().await {
|
||||
let row = row?;
|
||||
let Some(kind) = self.notification_kinds_by_id.get(&row.kind) else {
|
||||
continue;
|
||||
};
|
||||
result.notifications.push(proto::Notification {
|
||||
id: row.id.to_proto(),
|
||||
kind: row.kind as u32,
|
||||
kind: kind.to_string(),
|
||||
timestamp: row.created_at.assume_utc().unix_timestamp() as u64,
|
||||
is_read: row.is_read,
|
||||
entity_id_1: row.entity_id_1.map(|id| id as u64),
|
||||
entity_id_2: row.entity_id_2.map(|id| id as u64),
|
||||
entity_id_3: row.entity_id_3.map(|id| id as u64),
|
||||
content: row.content,
|
||||
actor_id: row.actor_id.map(|id| id.to_proto()),
|
||||
});
|
||||
}
|
||||
result.notifications.reverse();
|
||||
|
@ -55,26 +61,31 @@ impl Database {
|
|||
notification: Notification,
|
||||
tx: &DatabaseTransaction,
|
||||
) -> Result<proto::Notification> {
|
||||
let (kind, associated_entities) = notification.to_parts();
|
||||
let notification = notification.to_any();
|
||||
let kind = *self
|
||||
.notification_kinds_by_name
|
||||
.get(notification.kind.as_ref())
|
||||
.ok_or_else(|| anyhow!("invalid notification kind {:?}", notification.kind))?;
|
||||
|
||||
let model = notification::ActiveModel {
|
||||
recipient_id: ActiveValue::Set(recipient_id),
|
||||
kind: ActiveValue::Set(kind as i32),
|
||||
entity_id_1: ActiveValue::Set(associated_entities[0].map(|id| id as i32)),
|
||||
entity_id_2: ActiveValue::Set(associated_entities[1].map(|id| id as i32)),
|
||||
entity_id_3: ActiveValue::Set(associated_entities[2].map(|id| id as i32)),
|
||||
..Default::default()
|
||||
kind: ActiveValue::Set(kind),
|
||||
content: ActiveValue::Set(notification.content.clone()),
|
||||
actor_id: ActiveValue::Set(notification.actor_id.map(|id| UserId::from_proto(id))),
|
||||
is_read: ActiveValue::NotSet,
|
||||
created_at: ActiveValue::NotSet,
|
||||
id: ActiveValue::NotSet,
|
||||
}
|
||||
.save(&*tx)
|
||||
.await?;
|
||||
|
||||
Ok(proto::Notification {
|
||||
id: model.id.as_ref().to_proto(),
|
||||
kind: *model.kind.as_ref() as u32,
|
||||
kind: notification.kind.to_string(),
|
||||
timestamp: model.created_at.as_ref().assume_utc().unix_timestamp() as u64,
|
||||
is_read: false,
|
||||
entity_id_1: model.entity_id_1.as_ref().map(|id| id as u64),
|
||||
entity_id_2: model.entity_id_2.as_ref().map(|id| id as u64),
|
||||
entity_id_3: model.entity_id_3.as_ref().map(|id| id as u64),
|
||||
content: notification.content,
|
||||
actor_id: notification.actor_id,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::db::{NotificationId, UserId};
|
||||
use crate::db::{NotificationId, NotificationKindId, UserId};
|
||||
use sea_orm::entity::prelude::*;
|
||||
use time::PrimitiveDateTime;
|
||||
|
||||
|
@ -7,13 +7,12 @@ use time::PrimitiveDateTime;
|
|||
pub struct Model {
|
||||
#[sea_orm(primary_key)]
|
||||
pub id: NotificationId,
|
||||
pub recipient_id: UserId,
|
||||
pub kind: i32,
|
||||
pub is_read: bool,
|
||||
pub created_at: PrimitiveDateTime,
|
||||
pub entity_id_1: Option<i32>,
|
||||
pub entity_id_2: Option<i32>,
|
||||
pub entity_id_3: Option<i32>,
|
||||
pub recipient_id: UserId,
|
||||
pub actor_id: Option<UserId>,
|
||||
pub kind: NotificationKindId,
|
||||
pub content: String,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
use crate::db::NotificationKindId;
|
||||
use sea_orm::entity::prelude::*;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
|
||||
#[sea_orm(table_name = "notification_kinds")]
|
||||
pub struct Model {
|
||||
#[sea_orm(primary_key)]
|
||||
pub id: i32,
|
||||
pub id: NotificationKindId,
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ impl TestDb {
|
|||
let mut db = runtime.block_on(async {
|
||||
let mut options = ConnectOptions::new(url);
|
||||
options.max_connections(5);
|
||||
let db = Database::new(options, Executor::Deterministic(background))
|
||||
let mut db = Database::new(options, Executor::Deterministic(background))
|
||||
.await
|
||||
.unwrap();
|
||||
let sql = include_str!(concat!(
|
||||
|
@ -45,6 +45,7 @@ impl TestDb {
|
|||
))
|
||||
.await
|
||||
.unwrap();
|
||||
db.initialize_notification_enum().await.unwrap();
|
||||
db
|
||||
});
|
||||
|
||||
|
@ -79,11 +80,12 @@ impl TestDb {
|
|||
options
|
||||
.max_connections(5)
|
||||
.idle_timeout(Duration::from_secs(0));
|
||||
let db = Database::new(options, Executor::Deterministic(background))
|
||||
let mut db = Database::new(options, Executor::Deterministic(background))
|
||||
.await
|
||||
.unwrap();
|
||||
let migrations_path = concat!(env!("CARGO_MANIFEST_DIR"), "/migrations");
|
||||
db.migrate(Path::new(migrations_path), false).await.unwrap();
|
||||
db.initialize_notification_enum().await.unwrap();
|
||||
db
|
||||
});
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue