diff --git a/blah-types/src/lib.rs b/blah-types/src/lib.rs index 3ff9e52..051c7bc 100644 --- a/blah-types/src/lib.rs +++ b/blah-types/src/lib.rs @@ -405,7 +405,7 @@ pub struct RoomMetadata { /// `last_msg.cid`. /// This may or may not be a precise number. #[serde(skip_serializing_if = "Option::is_none")] - pub unseen_cnt: Option, + pub unseen_cnt: Option, /// The member permission of current user in the room, or `None` if it is not a member. /// Only available with authentication. #[serde(skip_serializing_if = "Option::is_none")] @@ -508,7 +508,7 @@ pub enum RoomAdminOp { bitflags::bitflags! { /// TODO: Is this a really all about permission, or is a generic `UserFlags`? #[derive(Debug, Clone, Copy, PartialEq, Eq)] - pub struct ServerPermission: u64 { + pub struct ServerPermission: i32 { const CREATE_ROOM = 1 << 0; const ACCEPT_PEER_CHAT = 1 << 16; @@ -517,7 +517,7 @@ bitflags::bitflags! { } #[derive(Debug, Clone, Copy, PartialEq, Eq)] - pub struct MemberPermission: u64 { + pub struct MemberPermission: i32 { const POST_CHAT = 1 << 0; const ADD_MEMBER = 1 << 1; const DELETE_ROOM = 1 << 2; @@ -529,7 +529,7 @@ bitflags::bitflags! { } #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] - pub struct RoomAttrs: u64 { + pub struct RoomAttrs: i32 { // NB. Used by schema. const PUBLIC_READABLE = 1 << 0; const PUBLIC_JOINABLE = 1 << 1; @@ -597,27 +597,25 @@ mod sql_impl { } } - macro_rules! impl_u64_flag { + macro_rules! impl_flag_to_from_sql { ($($name:ident),*) => { $( impl ToSql for $name { fn to_sql(&self) -> Result> { - // Cast out the sign. - Ok((self.bits() as i64).into()) + Ok(self.bits().into()) } } impl FromSql for $name { fn column_result(value: ValueRef<'_>) -> FromSqlResult { - // Cast out the sign. - i64::column_result(value).map(|v| $name::from_bits_retain(v as u64)) + i32::column_result(value).map($name::from_bits_retain) } } )* }; } - impl_u64_flag!(ServerPermission, MemberPermission, RoomAttrs); + impl_flag_to_from_sql!(ServerPermission, MemberPermission, RoomAttrs); } #[cfg(test)] diff --git a/blahd/src/database.rs b/blahd/src/database.rs index 5765b76..afe2bdd 100644 --- a/blahd/src/database.rs +++ b/blahd/src/database.rs @@ -19,6 +19,7 @@ mod tests; const DEFAULT_DATABASE_PATH: &str = "/var/lib/blahd/db.sqlite"; const STMT_CACHE_CAPACITY: usize = 24; +const UNSEEN_CNT_LIMIT: u32 = 999; static INIT_SQL: &str = include_str!("../schema.sql"); @@ -345,7 +346,6 @@ pub trait TransactionOps { start_rid: Id, page_len: usize, ) -> Result> { - // FIXME: Limit `unseen_cnt` counting. prepare_cached_and_bind!( self.conn(), r" @@ -354,10 +354,13 @@ pub trait TransactionOps { `cid`, `timestamp`, `nonce`, `sig`, `rich_text`, `last_author`.`id_key`, `msg`.`act_key`, `peer_user`.`id_key` AS `peer_id_key`, - (SELECT COUNT(*) + (SELECT COUNT(*) FROM ( + SELECT 1 FROM `msg` AS `unseen_msg` WHERE `unseen_msg`.`rid` = `room`.`rid` AND - `last_seen_cid` < `unseen_msg`.`cid`) AS `unseen_cnt` + `last_seen_cid` < `unseen_msg`.`cid` + LIMIT :UNSEEN_CNT_LIMIT + )) AS `unseen_cnt` FROM `room_member` INDEXED BY `ix_member_room` JOIN `room` USING (`rid`) LEFT JOIN `msg` USING (`rid`) diff --git a/docs/webapi.yaml b/docs/webapi.yaml index e4951e9..77fb5b7 100644 --- a/docs/webapi.yaml +++ b/docs/webapi.yaml @@ -506,7 +506,7 @@ components: attrs: description: Room attributes bitset, see `RoomAttrs`. type: integer - format: int64 + format: int32 last_msg: $ref: '#/components/schemas/WithMsgId-Signed-Chat' last_seen_cid: @@ -517,10 +517,10 @@ components: The number of unseen messages. Only available for GET `/room?filter=unseen`. type: integer - format: uint64 + format: uint32 member_permission: type: integer - format: int64 + format: int32 peer_user: type: string description: | @@ -536,7 +536,7 @@ components: type: string attrs: type: integer - format: int64 + format: int32 RoomMsgs: type: object @@ -644,7 +644,7 @@ components: type: string permission: type: integer - format: uint64 + format: int32 user: type: string