summaryrefslogtreecommitdiff
path: root/src/message
diff options
context:
space:
mode:
Diffstat (limited to 'src/message')
-rw-r--r--src/message/app.rs2
-rw-r--r--src/message/event.rs30
-rw-r--r--src/message/history.rs17
-rw-r--r--src/message/repo.rs125
-rw-r--r--src/message/routes.rs4
-rw-r--r--src/message/snapshot.rs49
6 files changed, 92 insertions, 135 deletions
diff --git a/src/message/app.rs b/src/message/app.rs
index 385c92e..3385af2 100644
--- a/src/message/app.rs
+++ b/src/message/app.rs
@@ -7,7 +7,7 @@ use crate::{
channel::{self, repo::Provider as _},
clock::DateTime,
db::NotFound as _,
- event::{broadcaster::Broadcaster, repo::Provider as _, Event, Sequence},
+ event::{repo::Provider as _, Broadcaster, Event, Sequence},
login::Login,
};
diff --git a/src/message/event.rs b/src/message/event.rs
index 66db9b0..1cd5847 100644
--- a/src/message/event.rs
+++ b/src/message/event.rs
@@ -1,29 +1,14 @@
use super::{snapshot::Message, Id};
-use crate::{
- channel::Channel,
- event::{Instant, Sequenced},
-};
+use crate::event::{Instant, Sequenced};
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize)]
-pub struct Event {
- #[serde(flatten)]
- pub kind: Kind,
-}
-
-impl Sequenced for Event {
- fn instant(&self) -> Instant {
- self.kind.instant()
- }
-}
-
-#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize)]
-#[serde(tag = "type", rename_all = "snake_case")]
-pub enum Kind {
+#[serde(tag = "event", rename_all = "snake_case")]
+pub enum Event {
Sent(Sent),
Deleted(Deleted),
}
-impl Sequenced for Kind {
+impl Sequenced for Event {
fn instant(&self) -> Instant {
match self {
Self::Sent(sent) => sent.instant(),
@@ -44,7 +29,7 @@ impl Sequenced for Sent {
}
}
-impl From<Sent> for Kind {
+impl From<Sent> for Event {
fn from(event: Sent) -> Self {
Self::Sent(event)
}
@@ -54,8 +39,7 @@ impl From<Sent> for Kind {
pub struct Deleted {
#[serde(flatten)]
pub instant: Instant,
- pub channel: Channel,
- pub message: Id,
+ pub id: Id,
}
impl Sequenced for Deleted {
@@ -64,7 +48,7 @@ impl Sequenced for Deleted {
}
}
-impl From<Deleted> for Kind {
+impl From<Deleted> for Event {
fn from(event: Deleted) -> Self {
Self::Deleted(event)
}
diff --git a/src/message/history.rs b/src/message/history.rs
index f267f4c..09e69b7 100644
--- a/src/message/history.rs
+++ b/src/message/history.rs
@@ -35,22 +35,19 @@ impl History {
// Events interface
impl History {
fn sent(&self) -> Event {
- Event {
- kind: Sent {
- message: self.message.clone(),
- }
- .into(),
+ Sent {
+ message: self.message.clone(),
}
+ .into()
}
fn deleted(&self) -> Option<Event> {
- self.deleted.map(|instant| Event {
- kind: Deleted {
+ self.deleted.map(|instant| {
+ Deleted {
instant,
- channel: self.message.channel.clone(),
- message: self.message.id.clone(),
+ id: self.message.id.clone(),
}
- .into(),
+ .into()
})
}
diff --git a/src/message/repo.rs b/src/message/repo.rs
index 5b199a7..71c6d10 100644
--- a/src/message/repo.rs
+++ b/src/message/repo.rs
@@ -2,7 +2,7 @@ use sqlx::{sqlite::Sqlite, SqliteConnection, Transaction};
use super::{snapshot::Message, History, Id};
use crate::{
- channel::{self, Channel},
+ channel,
clock::DateTime,
event::{Instant, ResumePoint, Sequence},
login::{self, Login},
@@ -38,6 +38,10 @@ impl<'c> Messages<'c> {
values ($1, $2, $3, $4, $5, $6)
returning
id as "id: Id",
+ channel as "channel: channel::Id",
+ sender as "sender: login::Id",
+ sent_at as "sent_at: DateTime",
+ sent_sequence as "sent_sequence: Sequence",
body
"#,
id,
@@ -49,12 +53,12 @@ impl<'c> Messages<'c> {
)
.map(|row| History {
message: Message {
- sent: *sent,
- // Use "as created" here as we don't care about providing a perfectly up-to-date
- // representation of the channel. The `name` is informational (and the ID, which is
- // normative, is fixed over time).
- channel: channel.as_created(),
- sender: sender.clone(),
+ sent: Instant {
+ at: row.sent_at,
+ sequence: row.sent_sequence,
+ },
+ channel: row.channel,
+ sender: row.sender,
id: row.id,
body: row.body,
},
@@ -75,20 +79,16 @@ impl<'c> Messages<'c> {
let messages = sqlx::query!(
r#"
select
- channel.id as "channel_id: channel::Id",
- channel.name as "channel_name",
- sender.id as "sender_id: login::Id",
- sender.name as "sender_name",
- message.id as "id: Id",
- message.body,
+ channel as "channel: channel::Id",
+ sender as "sender: login::Id",
+ id as "id: Id",
+ body,
sent_at as "sent_at: DateTime",
sent_sequence as "sent_sequence: Sequence"
from message
- join channel on message.channel = channel.id
- join login as sender on message.sender = sender.id
- where channel.id = $1
- and coalesce(message.sent_sequence <= $2, true)
- order by message.sent_sequence
+ where channel = $1
+ and coalesce(sent_sequence <= $2, true)
+ order by sent_sequence
"#,
channel_id,
resume_at,
@@ -99,14 +99,43 @@ impl<'c> Messages<'c> {
at: row.sent_at,
sequence: row.sent_sequence,
},
- channel: Channel {
- id: row.channel_id,
- name: row.channel_name,
- },
- sender: Login {
- id: row.sender_id,
- name: row.sender_name,
+ channel: row.channel,
+ sender: row.sender,
+ id: row.id,
+ body: row.body,
+ },
+ deleted: None,
+ })
+ .fetch_all(&mut *self.0)
+ .await?;
+
+ Ok(messages)
+ }
+
+ pub async fn all(&mut self, resume_at: ResumePoint) -> Result<Vec<History>, sqlx::Error> {
+ let messages = sqlx::query!(
+ r#"
+ select
+ channel as "channel: channel::Id",
+ sender as "sender: login::Id",
+ id as "id: Id",
+ body,
+ sent_at as "sent_at: DateTime",
+ sent_sequence as "sent_sequence: Sequence"
+ from message
+ where coalesce(sent_sequence <= $2, true)
+ order by sent_sequence
+ "#,
+ resume_at,
+ )
+ .map(|row| History {
+ message: Message {
+ sent: Instant {
+ at: row.sent_at,
+ sequence: row.sent_sequence,
},
+ channel: row.channel,
+ sender: row.sender,
id: row.id,
body: row.body,
},
@@ -122,18 +151,14 @@ impl<'c> Messages<'c> {
let message = sqlx::query!(
r#"
select
- channel.id as "channel_id: channel::Id",
- channel.name as "channel_name",
- sender.id as "sender_id: login::Id",
- sender.name as "sender_name",
- message.id as "id: Id",
- message.body,
+ channel as "channel: channel::Id",
+ sender as "sender: login::Id",
+ id as "id: Id",
+ body,
sent_at as "sent_at: DateTime",
sent_sequence as "sent_sequence: Sequence"
from message
- join channel on message.channel = channel.id
- join login as sender on message.sender = sender.id
- where message.id = $1
+ where id = $1
"#,
message,
)
@@ -143,14 +168,8 @@ impl<'c> Messages<'c> {
at: row.sent_at,
sequence: row.sent_sequence,
},
- channel: Channel {
- id: row.channel_id,
- name: row.channel_name,
- },
- sender: Login {
- id: row.sender_id,
- name: row.sender_name,
- },
+ channel: row.channel,
+ sender: row.sender,
id: row.id,
body: row.body,
},
@@ -207,17 +226,13 @@ impl<'c> Messages<'c> {
let messages = sqlx::query!(
r#"
select
- channel.id as "channel_id: channel::Id",
- channel.name as "channel_name",
- sender.id as "sender_id: login::Id",
- sender.name as "sender_name",
- message.id as "id: Id",
- message.body,
+ channel as "channel: channel::Id",
+ sender as "sender: login::Id",
+ id as "id: Id",
+ body,
sent_at as "sent_at: DateTime",
sent_sequence as "sent_sequence: Sequence"
from message
- join channel on message.channel = channel.id
- join login as sender on message.sender = sender.id
where coalesce(message.sent_sequence > $1, true)
"#,
resume_at,
@@ -228,14 +243,8 @@ impl<'c> Messages<'c> {
at: row.sent_at,
sequence: row.sent_sequence,
},
- channel: Channel {
- id: row.channel_id,
- name: row.channel_name,
- },
- sender: Login {
- id: row.sender_id,
- name: row.sender_name,
- },
+ channel: row.channel,
+ sender: row.sender,
id: row.id,
body: row.body,
},
diff --git a/src/message/routes.rs b/src/message/routes.rs
index 29fe3d7..e21c674 100644
--- a/src/message/routes.rs
+++ b/src/message/routes.rs
@@ -9,7 +9,7 @@ use axum::{
use crate::{
app::App,
clock::RequestedAt,
- error::Internal,
+ error::{Internal, NotFound},
login::Login,
message::{self, app::DeleteError},
};
@@ -38,7 +38,7 @@ impl IntoResponse for ErrorResponse {
let Self(error) = self;
match error {
not_found @ (DeleteError::ChannelNotFound(_) | DeleteError::NotFound(_)) => {
- (StatusCode::NOT_FOUND, not_found.to_string()).into_response()
+ NotFound(not_found).into_response()
}
other => Internal::from(other).into_response(),
}
diff --git a/src/message/snapshot.rs b/src/message/snapshot.rs
index 522c1aa..0eb37bb 100644
--- a/src/message/snapshot.rs
+++ b/src/message/snapshot.rs
@@ -1,57 +1,24 @@
use super::{
- event::{Event, Kind, Sent},
+ event::{Event, Sent},
Id,
};
-use crate::{channel::Channel, event::Instant, login::Login};
+use crate::{channel, event::Instant, login};
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize)]
-#[serde(into = "self::serialize::Message")]
pub struct Message {
- #[serde(skip)]
+ #[serde(flatten)]
pub sent: Instant,
- pub channel: Channel,
- pub sender: Login,
+ pub channel: channel::Id,
+ pub sender: login::Id,
pub id: Id,
pub body: String,
}
-mod serialize {
- use crate::{channel::Channel, login::Login, message::Id};
-
- #[derive(serde::Serialize)]
- pub struct Message {
- channel: Channel,
- sender: Login,
- #[allow(clippy::struct_field_names)]
- // Deliberately redundant with the module path; this produces a specific serialization.
- message: MessageData,
- }
-
- #[derive(serde::Serialize)]
- pub struct MessageData {
- id: Id,
- body: String,
- }
-
- impl From<super::Message> for Message {
- fn from(message: super::Message) -> Self {
- Self {
- channel: message.channel,
- sender: message.sender,
- message: MessageData {
- id: message.id,
- body: message.body,
- },
- }
- }
- }
-}
-
impl Message {
fn apply(state: Option<Self>, event: Event) -> Option<Self> {
- match (state, event.kind) {
- (None, Kind::Sent(event)) => Some(event.into()),
- (Some(message), Kind::Deleted(event)) if message.id == event.message => None,
+ match (state, event) {
+ (None, Event::Sent(event)) => Some(event.into()),
+ (Some(message), Event::Deleted(event)) if message.id == event.id => None,
(state, event) => panic!("invalid message event {event:#?} for state {state:#?}"),
}
}