diff options
| author | Owen Jacobson <owen@grimoire.ca> | 2025-06-20 19:47:46 -0400 |
|---|---|---|
| committer | Owen Jacobson <owen@grimoire.ca> | 2025-06-20 22:42:55 -0400 |
| commit | 7778cdf0c495a04f4f5f3f85b78348c8037a5771 (patch) | |
| tree | bd0e00d36ab1863f5609a3c0ee8936782ae794ca /src | |
| parent | 639f4b422adb0a6fc809161dd816d8382cf88138 (diff) | |
Remove the snapshot fields from `/api/boot`.
Clients now _must_ construct their state from the event stream; it is no longer possible for them to delegate that work to the server.
Diffstat (limited to 'src')
| -rw-r--r-- | src/boot/app.rs | 30 | ||||
| -rw-r--r-- | src/boot/handlers/boot/test.rs | 22 | ||||
| -rw-r--r-- | src/boot/mod.rs | 5 | ||||
| -rw-r--r-- | src/channel/handlers/create/test.rs | 10 | ||||
| -rw-r--r-- | src/channel/handlers/delete/test.rs | 12 | ||||
| -rw-r--r-- | src/channel/history.rs | 6 | ||||
| -rw-r--r-- | src/message/handlers/delete/test.rs | 10 | ||||
| -rw-r--r-- | src/message/history.rs | 6 | ||||
| -rw-r--r-- | src/user/history.rs | 8 |
9 files changed, 41 insertions, 68 deletions
diff --git a/src/boot/app.rs b/src/boot/app.rs index 690bcf4..89eec12 100644 --- a/src/boot/app.rs +++ b/src/boot/app.rs @@ -23,42 +23,27 @@ impl<'a> Boot<'a> { let mut tx = self.db.begin().await?; let resume_point = tx.sequence().current().await?; - let user_histories = tx.users().all(resume_point).await?; - let channel_histories = tx.channels().all(resume_point).await?; - let message_histories = tx.messages().all(resume_point).await?; + let users = tx.users().all(resume_point).await?; + let channels = tx.channels().all(resume_point).await?; + let messages = tx.messages().all(resume_point).await?; tx.commit().await?; - let users = user_histories - .iter() - .filter_map(|user| user.as_of(resume_point)) - .collect(); - - let channels = channel_histories - .iter() - .filter_map(|channel| channel.as_of(resume_point)) - .collect(); - - let messages = message_histories - .iter() - .filter_map(|message| message.as_of(resume_point)) - .collect(); - - let user_events = user_histories + let user_events = users .iter() .map(user::History::events) .kmerge_by(Sequence::merge) .filter(Sequence::up_to(resume_point)) .map(Event::from); - let channel_events = channel_histories + let channel_events = channels .iter() .map(channel::History::events) .kmerge_by(Sequence::merge) .filter(Sequence::up_to(resume_point)) .map(Event::from); - let message_events = message_histories + let message_events = messages .iter() .map(message::History::events) .kmerge_by(Sequence::merge) @@ -72,9 +57,6 @@ impl<'a> Boot<'a> { Ok(Snapshot { resume_point, - users, - channels, - messages, events, }) } diff --git a/src/boot/handlers/boot/test.rs b/src/boot/handlers/boot/test.rs index d68618e..1e590a7 100644 --- a/src/boot/handlers/boot/test.rs +++ b/src/boot/handlers/boot/test.rs @@ -25,8 +25,6 @@ async fn includes_users() { .await .expect("boot always succeeds"); - assert!(response.snapshot.users.contains(&spectator)); - let created = response .snapshot .events @@ -48,8 +46,6 @@ async fn includes_channels() { .await .expect("boot always succeeds"); - assert!(response.snapshot.channels.contains(&channel)); - let created = response .snapshot .events @@ -73,8 +69,6 @@ async fn includes_messages() { .await .expect("boot always succeeds"); - assert!(response.snapshot.messages.contains(&message)); - let sent = response .snapshot .events @@ -87,7 +81,7 @@ async fn includes_messages() { } #[tokio::test] -async fn excludes_expired_messages() { +async fn includes_expired_messages() { let app = fixtures::scratch_app().await; let sender = fixtures::user::create(&app, &fixtures::ancient()).await; let channel = fixtures::channel::create(&app, &fixtures::ancient()).await; @@ -104,8 +98,6 @@ async fn excludes_expired_messages() { .await .expect("boot always succeeds"); - assert!(!response.snapshot.messages.contains(&expired_message)); - let sent = response .snapshot .events @@ -131,7 +123,7 @@ async fn excludes_expired_messages() { } #[tokio::test] -async fn excludes_deleted_messages() { +async fn includes_deleted_messages() { let app = fixtures::scratch_app().await; let sender = fixtures::user::create(&app, &fixtures::now()).await; let channel = fixtures::channel::create(&app, &fixtures::now()).await; @@ -147,8 +139,6 @@ async fn excludes_deleted_messages() { .await .expect("boot always succeeds"); - assert!(!response.snapshot.messages.contains(&deleted_message)); - let sent = response .snapshot .events @@ -174,7 +164,7 @@ async fn excludes_deleted_messages() { } #[tokio::test] -async fn excludes_expired_channels() { +async fn includes_expired_channels() { let app = fixtures::scratch_app().await; let expired_channel = fixtures::channel::create(&app, &fixtures::ancient()).await; @@ -188,8 +178,6 @@ async fn excludes_expired_channels() { .await .expect("boot always succeeds"); - assert!(!response.snapshot.channels.contains(&expired_channel)); - let created = response .snapshot .events @@ -215,7 +203,7 @@ async fn excludes_expired_channels() { } #[tokio::test] -async fn excludes_deleted_channels() { +async fn includes_deleted_channels() { let app = fixtures::scratch_app().await; let deleted_channel = fixtures::channel::create(&app, &fixtures::now()).await; @@ -229,8 +217,6 @@ async fn excludes_deleted_channels() { .await .expect("boot always succeeds"); - assert!(!response.snapshot.channels.contains(&deleted_channel)); - let created = response .snapshot .events diff --git a/src/boot/mod.rs b/src/boot/mod.rs index 148e87d..e0d35d9 100644 --- a/src/boot/mod.rs +++ b/src/boot/mod.rs @@ -1,4 +1,4 @@ -use crate::{channel::Channel, event::Event, event::Sequence, message::Message, user::User}; +use crate::{event::Event, event::Sequence}; pub mod app; pub mod handlers; @@ -6,8 +6,5 @@ pub mod handlers; #[derive(serde::Serialize)] pub struct Snapshot { pub resume_point: Sequence, - pub users: Vec<User>, - pub channels: Vec<Channel>, - pub messages: Vec<Message>, pub events: Vec<Event>, } diff --git a/src/channel/handlers/create/test.rs b/src/channel/handlers/create/test.rs index 595a879..31bb778 100644 --- a/src/channel/handlers/create/test.rs +++ b/src/channel/handlers/create/test.rs @@ -2,6 +2,7 @@ use std::future; use axum::extract::{Json, State}; use futures::stream::StreamExt as _; +use itertools::Itertools; use crate::{ channel::app, @@ -33,7 +34,14 @@ async fn new_channel() { // Verify the semantics let snapshot = app.boot().snapshot().await.expect("boot always succeeds"); - assert!(snapshot.channels.iter().any(|channel| channel == &response)); + let created = snapshot + .events + .into_iter() + .filter_map(fixtures::event::channel) + .filter_map(fixtures::event::channel::created) + .exactly_one() + .expect("only one channel has been created"); + assert_eq!(response, created.channel); let channel = app .channels() diff --git a/src/channel/handlers/delete/test.rs b/src/channel/handlers/delete/test.rs index b1e42ea..99c19db 100644 --- a/src/channel/handlers/delete/test.rs +++ b/src/channel/handlers/delete/test.rs @@ -1,4 +1,5 @@ use axum::extract::{Path, State}; +use itertools::Itertools; use crate::{channel::app, test::fixtures}; @@ -28,7 +29,16 @@ pub async fn valid_channel() { // Verify the semantics let snapshot = app.boot().snapshot().await.expect("boot always succeeds"); - assert!(!snapshot.channels.contains(&channel)); + let created = snapshot + .events + .into_iter() + .filter_map(fixtures::event::channel) + .filter_map(fixtures::event::channel::created) + .exactly_one() + .expect("only one channel has been created"); + // We don't expect `channel` to match the event exactly, as the name will have been + // tombstoned and the channel given a `deleted_at` date. + assert_eq!(channel.id, created.channel.id); } #[tokio::test] diff --git a/src/channel/history.rs b/src/channel/history.rs index faf6a0e..7f18e45 100644 --- a/src/channel/history.rs +++ b/src/channel/history.rs @@ -27,12 +27,6 @@ impl History { self.channel.clone() } - pub fn as_of(&self, resume_point: Sequence) -> Option<Channel> { - self.events() - .filter(Sequence::up_to(resume_point)) - .collect() - } - // Snapshot of this channel as of all events recorded in this history. pub fn as_snapshot(&self) -> Option<Channel> { self.events().collect() diff --git a/src/message/handlers/delete/test.rs b/src/message/handlers/delete/test.rs index 15aa2c2..f567eb7 100644 --- a/src/message/handlers/delete/test.rs +++ b/src/message/handlers/delete/test.rs @@ -1,4 +1,5 @@ use axum::extract::{Path, State}; +use itertools::Itertools; use crate::{message::app, test::fixtures}; @@ -29,7 +30,14 @@ pub async fn delete_message() { // Verify the semantics let snapshot = app.boot().snapshot().await.expect("boot always succeeds"); - assert!(!snapshot.messages.contains(&message)); + let deleted = snapshot + .events + .into_iter() + .filter_map(fixtures::event::message) + .filter_map(fixtures::event::message::deleted) + .exactly_one() + .expect("only one message has been deleted"); + assert_eq!(response.id, deleted.id) } #[tokio::test] diff --git a/src/message/history.rs b/src/message/history.rs index 1a72c08..7585e1c 100644 --- a/src/message/history.rs +++ b/src/message/history.rs @@ -27,12 +27,6 @@ impl History { self.message.clone() } - pub fn as_of(&self, resume_point: Sequence) -> Option<Message> { - self.events() - .filter(Sequence::up_to(resume_point)) - .collect() - } - // Snapshot of this message as of all events recorded in this history. pub fn as_snapshot(&self) -> Option<Message> { self.events().collect() diff --git a/src/user/history.rs b/src/user/history.rs index ae7a561..72e0aee 100644 --- a/src/user/history.rs +++ b/src/user/history.rs @@ -2,7 +2,7 @@ use super::{ Id, User, event::{Created, Event}, }; -use crate::event::{Instant, Sequence}; +use crate::event::Instant; #[derive(Clone, Debug, Eq, PartialEq)] pub struct History { @@ -24,12 +24,6 @@ impl History { self.user.clone() } - pub fn as_of(&self, resume_point: Sequence) -> Option<User> { - self.events() - .filter(Sequence::up_to(resume_point)) - .collect() - } - // Snapshot of this user, as of all events recorded in this history. pub fn as_snapshot(&self) -> Option<User> { self.events().collect() |
