+12
spacedust/src/error.rs
+12
spacedust/src/error.rs
···
23
}
24
25
#[derive(Debug, Error)]
26
+
pub enum SubscriberUpdateError {
27
+
#[error("failed to parse json for subscriber update: {0}")]
28
+
FailedToParseMessage(serde_json::Error),
29
+
#[error("more wantedSources were requested than allowed (max 1,000)")]
30
+
TooManySourcesWanted,
31
+
#[error("more wantedSubjectDids were requested than allowed (max 10,000)")]
32
+
TooManyDidsWanted,
33
+
#[error("more wantedSubjects were requested than allowed (max 50,000)")]
34
+
TooManySubjectsWanted,
35
+
}
36
+
37
+
#[derive(Debug, Error)]
38
pub enum DelayError {
39
#[error("delay ended")]
40
DelayEnded,
+8
-1
spacedust/src/lib.rs
+8
-1
spacedust/src/lib.rs
···
8
use links::CollectedLink;
9
use jetstream::events::CommitEvent;
10
use tokio_tungstenite::tungstenite::Message;
11
-
use serde::Serialize;
12
13
#[derive(Debug)]
14
pub struct FilterableProperties {
···
84
// TODO: include the record too? would save clients a level of hydration
85
// ^^ no, not for now. until we backfill + support broader deletes at *least*.
86
}
···
8
use links::CollectedLink;
9
use jetstream::events::CommitEvent;
10
use tokio_tungstenite::tungstenite::Message;
11
+
use serde::{Deserialize, Serialize};
12
+
use server::MultiSubscribeQuery;
13
14
#[derive(Debug)]
15
pub struct FilterableProperties {
···
85
// TODO: include the record too? would save clients a level of hydration
86
// ^^ no, not for now. until we backfill + support broader deletes at *least*.
87
}
88
+
89
+
#[derive(Debug, Deserialize)]
90
+
#[serde(tag = "type", content = "payload", rename_all = "snake_case")]
91
+
pub enum SubscriberSourcedMessage {
92
+
OptionsUpdate(MultiSubscribeQuery),
93
+
}
+4
-2
spacedust/src/server.rs
+4
-2
spacedust/src/server.rs
···
19
use serde::{Deserialize, Serialize};
20
use tokio::sync::broadcast;
21
use tokio::time::Instant;
22
-
use tokio_tungstenite::tungstenite::protocol::Role;
23
use tokio_util::sync::CancellationToken;
24
use async_trait::async_trait;
25
use std::collections::HashSet;
···
315
let ws = tokio_tungstenite::WebSocketStream::from_raw_socket(
316
upgraded.into_inner(),
317
Role::Server,
318
-
None,
319
)
320
.await;
321
···
19
use serde::{Deserialize, Serialize};
20
use tokio::sync::broadcast;
21
use tokio::time::Instant;
22
+
use tokio_tungstenite::tungstenite::protocol::{Role, WebSocketConfig};
23
use tokio_util::sync::CancellationToken;
24
use async_trait::async_trait;
25
use std::collections::HashSet;
···
315
let ws = tokio_tungstenite::WebSocketStream::from_raw_socket(
316
upgraded.into_inner(),
317
Role::Server,
318
+
Some(WebSocketConfig::default().max_message_size(
319
+
Some(10 * 2_usize.pow(20)) // 10MiB, matching jetstream
320
+
)),
321
)
322
.await;
323
+30
-2
spacedust/src/subscriber.rs
+30
-2
spacedust/src/subscriber.rs
···
1
use std::sync::Arc;
2
use tokio::time::interval;
3
use std::time::Duration;
4
use futures::StreamExt;
5
-
use crate::{ClientMessage, FilterableProperties};
6
use crate::server::MultiSubscribeQuery;
7
use futures::SinkExt;
8
use std::error::Error;
···
27
}
28
29
pub async fn start(
30
-
self,
31
ws: WebSocketStream<WebsocketConnectionRaw>,
32
mut receiver: broadcast::Receiver<Arc<ClientMessage>>
33
) -> Result<(), Box<dyn Error>> {
···
76
self.shutdown.cancel();
77
}
78
}
79
Some(Ok(m)) => log::trace!("subscriber sent an unexpected message: {m:?}"),
80
Some(Err(e)) => {
81
log::error!("failed to receive subscriber message: {e:?}");
···
137
true
138
}
139
}
···
1
+
use crate::error::SubscriberUpdateError;
2
use std::sync::Arc;
3
use tokio::time::interval;
4
use std::time::Duration;
5
use futures::StreamExt;
6
+
use crate::{ClientMessage, FilterableProperties, SubscriberSourcedMessage};
7
use crate::server::MultiSubscribeQuery;
8
use futures::SinkExt;
9
use std::error::Error;
···
28
}
29
30
pub async fn start(
31
+
mut self,
32
ws: WebSocketStream<WebsocketConnectionRaw>,
33
mut receiver: broadcast::Receiver<Arc<ClientMessage>>
34
) -> Result<(), Box<dyn Error>> {
···
77
self.shutdown.cancel();
78
}
79
}
80
+
Some(Ok(Message::Text(raw))) => {
81
+
if let Err(e) = self.query.update_from_raw(&raw) {
82
+
log::error!("subscriber options could not be updated, dropping: {e:?}");
83
+
// TODO: send client an explanation
84
+
self.shutdown.cancel();
85
+
}
86
+
},
87
Some(Ok(m)) => log::trace!("subscriber sent an unexpected message: {m:?}"),
88
Some(Err(e)) => {
89
log::error!("failed to receive subscriber message: {e:?}");
···
145
true
146
}
147
}
148
+
149
+
150
+
151
+
impl MultiSubscribeQuery {
152
+
pub fn update_from_raw(&mut self, s: &str) -> Result<(), SubscriberUpdateError> {
153
+
let SubscriberSourcedMessage::OptionsUpdate(opts) = serde_json::from_str(s)
154
+
.map_err(SubscriberUpdateError::FailedToParseMessage)?;
155
+
if opts.wanted_sources.len() > 1_000 {
156
+
return Err(SubscriberUpdateError::TooManySourcesWanted);
157
+
}
158
+
if opts.wanted_subject_dids.len() > 10_000 {
159
+
return Err(SubscriberUpdateError::TooManyDidsWanted);
160
+
}
161
+
if opts.wanted_subjects.len() > 50_000 {
162
+
return Err(SubscriberUpdateError::TooManySubjectsWanted);
163
+
}
164
+
*self = opts;
165
+
Ok(())
166
+
}
167
+
}