notedeck

One damus client to rule them all
git clone git://jb55.com/notedeck
Log | Files | Refs | README | LICENSE

commit 0d7b012caf8dc87de5ca6a26f512031b1bd821b9
parent d9c2af4f22ff6b00875fe89f627b082250c02a34
Author: kernelkind <kernelkind@gmail.com>
Date:   Mon,  2 Feb 2026 13:55:07 -0500

feat(outbox): add `OutboxSessionHandler`

Signed-off-by: kernelkind <kernelkind@gmail.com>

Diffstat:
Mcrates/enostr/src/relay/mod.rs | 2+-
Acrates/enostr/src/relay/outbox/handler.rs | 83+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mcrates/enostr/src/relay/outbox/mod.rs | 2++
3 files changed, 86 insertions(+), 1 deletion(-)

diff --git a/crates/enostr/src/relay/mod.rs b/crates/enostr/src/relay/mod.rs @@ -22,7 +22,7 @@ pub use limits::{ }; pub use multicast::{MulticastRelay, MulticastRelayCache}; use nostrdb::Filter; -pub use outbox::{OutboxPool, OutboxSession}; +pub use outbox::{OutboxPool, OutboxSession, OutboxSessionHandler}; pub use queue::QueuedTasks; pub use subscription::{ FullModificationTask, ModifyFiltersTask, ModifyRelaysTask, ModifyTask, OutboxSubscriptions, diff --git a/crates/enostr/src/relay/outbox/handler.rs b/crates/enostr/src/relay/outbox/handler.rs @@ -0,0 +1,83 @@ +use hashbrown::HashSet; +use nostrdb::{Filter, Note}; + +use crate::relay::outbox::OutboxPool; +use crate::relay::{NormRelayUrl, OutboxSubId, RelayId, RelayUrlPkgs}; +use crate::{relay::outbox::OutboxSession, Wakeup}; + +/// OutboxSessionHandler is the RAII wrapper apps use to stage subscription +/// updates; dropping it flushes the recorded operations into the OutboxPool. +pub struct OutboxSessionHandler<'a, W> +where + W: Wakeup, +{ + pub outbox: &'a mut OutboxPool, + pub(crate) session: OutboxSession, + pub(crate) wakeup: W, +} + +impl<'a, W> Drop for OutboxSessionHandler<'a, W> +where + W: Wakeup, +{ + fn drop(&mut self) { + let session = std::mem::take(&mut self.session); + self.outbox.ingest_session(session, &self.wakeup); + } +} + +impl<'a, W> OutboxSessionHandler<'a, W> +where + W: Wakeup, +{ + pub fn new(outbox: &'a mut OutboxPool, wakeup: W) -> Self { + Self { + outbox, + session: OutboxSession::default(), + wakeup, + } + } + + pub fn subscribe(&mut self, filters: Vec<Filter>, urls: RelayUrlPkgs) -> OutboxSubId { + let new_id = self.outbox.registry.next(); + self.session.subscribe(new_id, filters, urls); + new_id + } + + pub fn oneshot(&mut self, filters: Vec<Filter>, urls: RelayUrlPkgs) { + let new_id = self.outbox.registry.next(); + self.session.oneshot(new_id, filters, urls); + } + + pub fn modify_filters(&mut self, id: OutboxSubId, filters: Vec<Filter>) { + self.session.new_filters(id, filters); + } + + pub fn modify_relays(&mut self, id: OutboxSubId, relays: HashSet<NormRelayUrl>) { + self.session.new_relays(id, relays); + } + + pub fn unsubscribe(&mut self, id: OutboxSubId) { + self.session.unsubscribe(id); + } + + pub fn broadcast_note(&mut self, note: &Note, relays: Vec<RelayId>) { + self.outbox.broadcast_note(note, relays, &self.wakeup); + } + + /// Eject the session from the handler. + /// This is only necessary between initialization of the app and the first frame + pub fn export(mut self) -> OutboxSession { + let session = std::mem::take(&mut self.session); + drop(self); + session + } + + pub fn import(outbox: &'a mut OutboxPool, session: OutboxSession, wakeup: W) -> Self { + Self { + outbox, + session, + wakeup, + } + } +} diff --git a/crates/enostr/src/relay/outbox/mod.rs b/crates/enostr/src/relay/outbox/mod.rs @@ -16,8 +16,10 @@ use crate::{ EventClientMessage, Wakeup, WebsocketConn, }; +mod handler; mod session; +pub use handler::OutboxSessionHandler; pub use session::OutboxSession; const KEEPALIVE_PING_RATE: Duration = Duration::from_secs(45);