Add local in-memory pubsub

This commit is contained in:
Eric Wendland 2026-05-17 18:23:51 +02:00
commit 6c85a341b8
13 changed files with 246 additions and 14 deletions

View file

@ -7,4 +7,5 @@ license.workspace = true
[dependencies]
serde.workspace = true
thiserror.workspace = true
geth-types = { path = "../geth-types" }

View file

@ -1,4 +1,4 @@
use geth_types::{ResourceId, TopicId};
use geth_types::{ResourceId, TopicId, UnixMillis};
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
@ -8,7 +8,54 @@ pub struct PubsubTopic {
pub name: String,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct PubsubMessage {
pub topic: TopicId,
pub message: String,
pub published_at: UnixMillis,
}
#[derive(Debug, thiserror::Error)]
pub enum PubsubError {
#[error("invalid pubsub topic: {0}")]
InvalidTopic(String),
#[error("pubsub message must not be empty")]
EmptyMessage,
}
pub fn validate_topic(topic: &str) -> Result<(), PubsubError> {
if topic.is_empty()
|| topic
.bytes()
.any(|byte| byte == 0 || byte == b'\n' || byte == b'\r')
{
return Err(PubsubError::InvalidTopic(topic.to_owned()));
}
Ok(())
}
pub fn validate_message(message: &str) -> Result<(), PubsubError> {
if message.is_empty() {
return Err(PubsubError::EmptyMessage);
}
Ok(())
}
#[must_use]
pub fn pubsub_storage_warning() -> &'static str {
"pubsub is lossy notification transport, not authoritative storage"
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn pubsub_validation_rejects_invalid_topics_and_empty_messages() {
assert!(validate_topic("presence/laptop").is_ok());
assert!(validate_topic("").is_err());
assert!(validate_topic("presence\nlaptop").is_err());
assert!(validate_message("online").is_ok());
assert!(validate_message("").is_err());
}
}