atagen

vineyard

public
Star0
Watch0
25d14e49ab6861630869e2129d40652900bc5833
1
ssh://brewery@pls.lobotomise.me:33/atagen/vineyard.git

Blame: src/relay.rs

25d14e49ab68atagen2026-09-24 11:07 UTC1
use std::collections::{BTreeSet, HashMap};
25d14e49ab68atagen2026-09-24 11:07 UTC2
use std::net::SocketAddr;
25d14e49ab68atagen2026-09-24 11:07 UTC3
use std::sync::Arc;
25d14e49ab68atagen2026-09-24 11:07 UTC4
use std::time::Duration;
25d14e49ab68atagen2026-09-24 11:07 UTC5
25d14e49ab68atagen2026-09-24 11:07 UTC6
use anyhow::{Context as _, Result};
25d14e49ab68atagen2026-09-24 11:07 UTC7
use futures_util::{Sink, SinkExt as _, StreamExt as _};
25d14e49ab68atagen2026-09-24 11:07 UTC8
use nostr::event::Event;
25d14e49ab68atagen2026-09-24 11:07 UTC9
use nostr::filter::{Filter, MatchEventOptions};
25d14e49ab68atagen2026-09-24 11:07 UTC10
use nostr_database::{NostrDatabase as _, RejectedReason, SaveEventStatus};
25d14e49ab68atagen2026-09-24 11:07 UTC11
use serde_json::{Value, json};
25d14e49ab68atagen2026-09-24 11:07 UTC12
use tokio::io::{AsyncRead, AsyncWrite};
25d14e49ab68atagen2026-09-24 11:07 UTC13
use tokio::sync::broadcast;
25d14e49ab68atagen2026-09-24 11:07 UTC14
use tokio::time::timeout;
25d14e49ab68atagen2026-09-24 11:07 UTC15
use tokio_tungstenite::WebSocketStream;
25d14e49ab68atagen2026-09-24 11:07 UTC16
use tokio_tungstenite::tungstenite::{
25d14e49ab68atagen2026-09-24 11:07 UTC17
    Error as WebSocketError, Message,
25d14e49ab68atagen2026-09-24 11:07 UTC18
    protocol::{Role, WebSocketConfig},
25d14e49ab68atagen2026-09-24 11:07 UTC19
};
25d14e49ab68atagen2026-09-24 11:07 UTC20
use tokio_util::sync::CancellationToken;
25d14e49ab68atagen2026-09-24 11:07 UTC21
25d14e49ab68atagen2026-09-24 11:07 UTC22
use crate::config::Limits;
25d14e49ab68atagen2026-09-24 11:07 UTC23
use crate::policy::{Policy, QueryPolicyResult, WritePolicyResult};
25d14e49ab68atagen2026-09-24 11:07 UTC24
use crate::store::Store;
25d14e49ab68atagen2026-09-24 11:07 UTC25
25d14e49ab68atagen2026-09-24 11:07 UTC26
#[derive(Clone)]
25d14e49ab68atagen2026-09-24 11:07 UTC27
pub struct Relay {
25d14e49ab68atagen2026-09-24 11:07 UTC28
    store: Arc<Store>,
25d14e49ab68atagen2026-09-24 11:07 UTC29
    policy: Policy,
25d14e49ab68atagen2026-09-24 11:07 UTC30
    limits: Limits,
25d14e49ab68atagen2026-09-24 11:07 UTC31
    events: broadcast::Sender<Event>,
25d14e49ab68atagen2026-09-24 11:07 UTC32
    stop: CancellationToken,
25d14e49ab68atagen2026-09-24 11:07 UTC33
}
25d14e49ab68atagen2026-09-24 11:07 UTC34
25d14e49ab68atagen2026-09-24 11:07 UTC35
struct Subscription {
25d14e49ab68atagen2026-09-24 11:07 UTC36
    filters: Vec<Filter>,
25d14e49ab68atagen2026-09-24 11:07 UTC37
    bytes: usize,
25d14e49ab68atagen2026-09-24 11:07 UTC38
}
25d14e49ab68atagen2026-09-24 11:07 UTC39
25d14e49ab68atagen2026-09-24 11:07 UTC40
#[derive(Default)]
25d14e49ab68atagen2026-09-24 11:07 UTC41
struct Session {
25d14e49ab68atagen2026-09-24 11:07 UTC42
    subscriptions: HashMap<String, Subscription>,
25d14e49ab68atagen2026-09-24 11:07 UTC43
}
25d14e49ab68atagen2026-09-24 11:07 UTC44
25d14e49ab68atagen2026-09-24 11:07 UTC45
impl Relay {
25d14e49ab68atagen2026-09-24 11:07 UTC46
    pub(crate) fn new(
25d14e49ab68atagen2026-09-24 11:07 UTC47
        store: Arc<Store>,
25d14e49ab68atagen2026-09-24 11:07 UTC48
        policy: Policy,
25d14e49ab68atagen2026-09-24 11:07 UTC49
        limits: Limits,
25d14e49ab68atagen2026-09-24 11:07 UTC50
        stop: CancellationToken,
25d14e49ab68atagen2026-09-24 11:07 UTC51
    ) -> Self {
25d14e49ab68atagen2026-09-24 11:07 UTC52
        let (events, _) = broadcast::channel(limits.max_connections.max(32));
25d14e49ab68atagen2026-09-24 11:07 UTC53
        Self {
25d14e49ab68atagen2026-09-24 11:07 UTC54
            store,
25d14e49ab68atagen2026-09-24 11:07 UTC55
            policy,
25d14e49ab68atagen2026-09-24 11:07 UTC56
            limits,
25d14e49ab68atagen2026-09-24 11:07 UTC57
            events,
25d14e49ab68atagen2026-09-24 11:07 UTC58
            stop,
25d14e49ab68atagen2026-09-24 11:07 UTC59
        }
25d14e49ab68atagen2026-09-24 11:07 UTC60
    }
25d14e49ab68atagen2026-09-24 11:07 UTC61
25d14e49ab68atagen2026-09-24 11:07 UTC62
    pub(crate) async fn add_event(&self, event: Event) -> Result<SaveEventStatus> {
25d14e49ab68atagen2026-09-24 11:07 UTC63
        event.verify().context("invalid event")?;
25d14e49ab68atagen2026-09-24 11:07 UTC64
        let status = self.store.save_event(&event).await?;
25d14e49ab68atagen2026-09-24 11:07 UTC65
        if status.is_success() {
25d14e49ab68atagen2026-09-24 11:07 UTC66
            match self.events.send(event) {
25d14e49ab68atagen2026-09-24 11:07 UTC67
                Ok(_) | Err(_) => {}
25d14e49ab68atagen2026-09-24 11:07 UTC68
            }
25d14e49ab68atagen2026-09-24 11:07 UTC69
        }
25d14e49ab68atagen2026-09-24 11:07 UTC70
        Ok(status)
25d14e49ab68atagen2026-09-24 11:07 UTC71
    }
25d14e49ab68atagen2026-09-24 11:07 UTC72
25d14e49ab68atagen2026-09-24 11:07 UTC73
    pub(crate) async fn take_connection<S>(&self, stream: S, address: SocketAddr) -> Result<()>
25d14e49ab68atagen2026-09-24 11:07 UTC74
    where
25d14e49ab68atagen2026-09-24 11:07 UTC75
        S: AsyncRead + AsyncWrite + Unpin,
25d14e49ab68atagen2026-09-24 11:07 UTC76
    {
25d14e49ab68atagen2026-09-24 11:07 UTC77
        let websocket = WebSocketStream::from_raw_socket(
25d14e49ab68atagen2026-09-24 11:07 UTC78
            stream,
25d14e49ab68atagen2026-09-24 11:07 UTC79
            Role::Server,
25d14e49ab68atagen2026-09-24 11:07 UTC80
            Some(
25d14e49ab68atagen2026-09-24 11:07 UTC81
                WebSocketConfig::default()
25d14e49ab68atagen2026-09-24 11:07 UTC82
                    .max_message_size(Some(self.limits.max_message_bytes))
25d14e49ab68atagen2026-09-24 11:07 UTC83
                    .max_frame_size(Some(self.limits.max_message_bytes)),
25d14e49ab68atagen2026-09-24 11:07 UTC84
            ),
25d14e49ab68atagen2026-09-24 11:07 UTC85
        )
25d14e49ab68atagen2026-09-24 11:07 UTC86
        .await;
25d14e49ab68atagen2026-09-24 11:07 UTC87
        let (mut sink, mut source) = websocket.split();
25d14e49ab68atagen2026-09-24 11:07 UTC88
        let mut events = self.events.subscribe();
25d14e49ab68atagen2026-09-24 11:07 UTC89
        let mut session = Session::default();
25d14e49ab68atagen2026-09-24 11:07 UTC90
25d14e49ab68atagen2026-09-24 11:07 UTC91
        loop {
25d14e49ab68atagen2026-09-24 11:07 UTC92
            tokio::select! {
25d14e49ab68atagen2026-09-24 11:07 UTC93
                biased;
25d14e49ab68atagen2026-09-24 11:07 UTC94
                () = self.stop.cancelled() => return Ok(()),
25d14e49ab68atagen2026-09-24 11:07 UTC95
                received = source.next() => {
25d14e49ab68atagen2026-09-24 11:07 UTC96
                    let Some(message) = received else { return Ok(()); };
25d14e49ab68atagen2026-09-24 11:07 UTC97
                    match message? {
25d14e49ab68atagen2026-09-24 11:07 UTC98
                        Message::Text(text) => {
25d14e49ab68atagen2026-09-24 11:07 UTC99
                            for response in self.handle_text(&mut session, address, &text).await {
25d14e49ab68atagen2026-09-24 11:07 UTC100
                                self.send(&mut sink, response).await?;
25d14e49ab68atagen2026-09-24 11:07 UTC101
                            }
25d14e49ab68atagen2026-09-24 11:07 UTC102
                        }
25d14e49ab68atagen2026-09-24 11:07 UTC103
                        Message::Ping(payload) => {
25d14e49ab68atagen2026-09-24 11:07 UTC104
                            self.send_message(&mut sink, Message::Pong(payload)).await?;
25d14e49ab68atagen2026-09-24 11:07 UTC105
                        }
25d14e49ab68atagen2026-09-24 11:07 UTC106
                        Message::Close(_) => return Ok(()),
25d14e49ab68atagen2026-09-24 11:07 UTC107
                        Message::Binary(_) | Message::Pong(_) | Message::Frame(_) => {}
25d14e49ab68atagen2026-09-24 11:07 UTC108
                    }
25d14e49ab68atagen2026-09-24 11:07 UTC109
                }
25d14e49ab68atagen2026-09-24 11:07 UTC110
                received = events.recv() => {
25d14e49ab68atagen2026-09-24 11:07 UTC111
                    let event = received.context("live event stream lagged")?;
25d14e49ab68atagen2026-09-24 11:07 UTC112
                    let ids = session.subscriptions.iter()
25d14e49ab68atagen2026-09-24 11:07 UTC113
                        .filter(|entry| entry.1.filters.iter().any(|filter| filter.match_event(&event, MatchEventOptions::new())))
25d14e49ab68atagen2026-09-24 11:07 UTC114
                        .map(|entry| entry.0.clone())
25d14e49ab68atagen2026-09-24 11:07 UTC115
                        .collect::<Vec<_>>();
25d14e49ab68atagen2026-09-24 11:07 UTC116
                    for id in ids {
25d14e49ab68atagen2026-09-24 11:07 UTC117
                        self.send(&mut sink, json!(["EVENT", id, event])).await?;
25d14e49ab68atagen2026-09-24 11:07 UTC118
                    }
25d14e49ab68atagen2026-09-24 11:07 UTC119
                }
25d14e49ab68atagen2026-09-24 11:07 UTC120
            }
25d14e49ab68atagen2026-09-24 11:07 UTC121
        }
25d14e49ab68atagen2026-09-24 11:07 UTC122
    }
25d14e49ab68atagen2026-09-24 11:07 UTC123
25d14e49ab68atagen2026-09-24 11:07 UTC124
    async fn send<S>(&self, sink: &mut S, value: Value) -> Result<()>
25d14e49ab68atagen2026-09-24 11:07 UTC125
    where
25d14e49ab68atagen2026-09-24 11:07 UTC126
        S: Sink<Message, Error = WebSocketError> + Unpin,
25d14e49ab68atagen2026-09-24 11:07 UTC127
    {
25d14e49ab68atagen2026-09-24 11:07 UTC128
        self.send_message(sink, Message::Text(value.to_string().into()))
25d14e49ab68atagen2026-09-24 11:07 UTC129
            .await
25d14e49ab68atagen2026-09-24 11:07 UTC130
    }
25d14e49ab68atagen2026-09-24 11:07 UTC131
25d14e49ab68atagen2026-09-24 11:07 UTC132
    async fn send_message<S>(&self, sink: &mut S, message: Message) -> Result<()>
25d14e49ab68atagen2026-09-24 11:07 UTC133
    where
25d14e49ab68atagen2026-09-24 11:07 UTC134
        S: Sink<Message, Error = WebSocketError> + Unpin,
25d14e49ab68atagen2026-09-24 11:07 UTC135
    {
25d14e49ab68atagen2026-09-24 11:07 UTC136
        timeout(
25d14e49ab68atagen2026-09-24 11:07 UTC137
            Duration::from_secs(self.limits.write_timeout_seconds),
25d14e49ab68atagen2026-09-24 11:07 UTC138
            sink.send(message),
25d14e49ab68atagen2026-09-24 11:07 UTC139
        )
25d14e49ab68atagen2026-09-24 11:07 UTC140
        .await
25d14e49ab68atagen2026-09-24 11:07 UTC141
        .context("websocket write timed out")??;
25d14e49ab68atagen2026-09-24 11:07 UTC142
        Ok(())
25d14e49ab68atagen2026-09-24 11:07 UTC143
    }
25d14e49ab68atagen2026-09-24 11:07 UTC144
25d14e49ab68atagen2026-09-24 11:07 UTC145
    async fn handle_text(
25d14e49ab68atagen2026-09-24 11:07 UTC146
        &self,
25d14e49ab68atagen2026-09-24 11:07 UTC147
        session: &mut Session,
25d14e49ab68atagen2026-09-24 11:07 UTC148
        address: SocketAddr,
25d14e49ab68atagen2026-09-24 11:07 UTC149
        text: &str,
25d14e49ab68atagen2026-09-24 11:07 UTC150
    ) -> Vec<Value> {
25d14e49ab68atagen2026-09-24 11:07 UTC151
        let Ok(value) = serde_json::from_str::<Value>(text) else {
25d14e49ab68atagen2026-09-24 11:07 UTC152
            return vec![json!(["NOTICE", "invalid json"])];
25d14e49ab68atagen2026-09-24 11:07 UTC153
        };
25d14e49ab68atagen2026-09-24 11:07 UTC154
        let Some(frame) = value.as_array() else {
25d14e49ab68atagen2026-09-24 11:07 UTC155
            return vec![json!(["NOTICE", "message must be an array"])];
25d14e49ab68atagen2026-09-24 11:07 UTC156
        };
25d14e49ab68atagen2026-09-24 11:07 UTC157
        match frame.first().and_then(Value::as_str) {
25d14e49ab68atagen2026-09-24 11:07 UTC158
            Some("EVENT") => vec![self.handle_event(frame, address).await],
25d14e49ab68atagen2026-09-24 11:07 UTC159
            Some("REQ") => self.handle_req(session, frame, address, text.len()).await,
25d14e49ab68atagen2026-09-24 11:07 UTC160
            Some("CLOSE") => {
25d14e49ab68atagen2026-09-24 11:07 UTC161
                if let Some(id) = frame.get(1).and_then(Value::as_str) {
25d14e49ab68atagen2026-09-24 11:07 UTC162
                    session.subscriptions.remove(id);
25d14e49ab68atagen2026-09-24 11:07 UTC163
                }
25d14e49ab68atagen2026-09-24 11:07 UTC164
                Vec::new()
25d14e49ab68atagen2026-09-24 11:07 UTC165
            }
25d14e49ab68atagen2026-09-24 11:07 UTC166
            _ => vec![json!(["NOTICE", "unsupported message"])],
25d14e49ab68atagen2026-09-24 11:07 UTC167
        }
25d14e49ab68atagen2026-09-24 11:07 UTC168
    }
25d14e49ab68atagen2026-09-24 11:07 UTC169
25d14e49ab68atagen2026-09-24 11:07 UTC170
    async fn handle_event(&self, frame: &[Value], address: SocketAddr) -> Value {
25d14e49ab68atagen2026-09-24 11:07 UTC171
        let Some(value) = frame.get(1) else {
25d14e49ab68atagen2026-09-24 11:07 UTC172
            return json!(["NOTICE", "EVENT requires an event"]);
25d14e49ab68atagen2026-09-24 11:07 UTC173
        };
25d14e49ab68atagen2026-09-24 11:07 UTC174
        let id = value
25d14e49ab68atagen2026-09-24 11:07 UTC175
            .get("id")
25d14e49ab68atagen2026-09-24 11:07 UTC176
            .and_then(Value::as_str)
25d14e49ab68atagen2026-09-24 11:07 UTC177
            .unwrap_or_default()
25d14e49ab68atagen2026-09-24 11:07 UTC178
            .to_owned();
25d14e49ab68atagen2026-09-24 11:07 UTC179
        let Ok(event) = serde_json::from_value::<Event>(value.clone()) else {
25d14e49ab68atagen2026-09-24 11:07 UTC180
            return json!(["OK", id, false, "invalid: malformed event"]);
25d14e49ab68atagen2026-09-24 11:07 UTC181
        };
25d14e49ab68atagen2026-09-24 11:07 UTC182
        if event.verify().is_err() {
25d14e49ab68atagen2026-09-24 11:07 UTC183
            return json!(["OK", event.id, false, "invalid: bad id or signature"]);
25d14e49ab68atagen2026-09-24 11:07 UTC184
        }
25d14e49ab68atagen2026-09-24 11:07 UTC185
        match self.policy.admit_event(&event, &address).await {
25d14e49ab68atagen2026-09-24 11:07 UTC186
            WritePolicyResult::Accept => {}
25d14e49ab68atagen2026-09-24 11:07 UTC187
            WritePolicyResult::Respond {
25d14e49ab68atagen2026-09-24 11:07 UTC188
                prefix,
25d14e49ab68atagen2026-09-24 11:07 UTC189
                message,
25d14e49ab68atagen2026-09-24 11:07 UTC190
                status,
25d14e49ab68atagen2026-09-24 11:07 UTC191
            } => return json!(["OK", event.id, status, format!("{prefix}: {message}")]),
25d14e49ab68atagen2026-09-24 11:07 UTC192
        }
25d14e49ab68atagen2026-09-24 11:07 UTC193
        let event_id = event.id;
25d14e49ab68atagen2026-09-24 11:07 UTC194
        match self.add_event(event).await {
25d14e49ab68atagen2026-09-24 11:07 UTC195
            Ok(SaveEventStatus::Success) => json!(["OK", event_id, true, ""]),
25d14e49ab68atagen2026-09-24 11:07 UTC196
            Ok(SaveEventStatus::Rejected(RejectedReason::Duplicate)) => {
25d14e49ab68atagen2026-09-24 11:07 UTC197
                json!(["OK", event_id, true, "duplicate: already stored"])
25d14e49ab68atagen2026-09-24 11:07 UTC198
            }
25d14e49ab68atagen2026-09-24 11:07 UTC199
            Ok(SaveEventStatus::Rejected(reason)) => {
25d14e49ab68atagen2026-09-24 11:07 UTC200
                json!(["OK", event_id, false, format!("blocked: {reason:?}")])
25d14e49ab68atagen2026-09-24 11:07 UTC201
            }
25d14e49ab68atagen2026-09-24 11:07 UTC202
            Err(error) => {
25d14e49ab68atagen2026-09-24 11:07 UTC203
                tracing::error!(event = %event_id, %error, "event storage failed");
25d14e49ab68atagen2026-09-24 11:07 UTC204
                json!(["OK", event_id, false, "error: database unavailable"])
25d14e49ab68atagen2026-09-24 11:07 UTC205
            }
25d14e49ab68atagen2026-09-24 11:07 UTC206
        }
25d14e49ab68atagen2026-09-24 11:07 UTC207
    }
25d14e49ab68atagen2026-09-24 11:07 UTC208
25d14e49ab68atagen2026-09-24 11:07 UTC209
    async fn handle_req(
25d14e49ab68atagen2026-09-24 11:07 UTC210
        &self,
25d14e49ab68atagen2026-09-24 11:07 UTC211
        session: &mut Session,
25d14e49ab68atagen2026-09-24 11:07 UTC212
        frame: &[Value],
25d14e49ab68atagen2026-09-24 11:07 UTC213
        address: SocketAddr,
25d14e49ab68atagen2026-09-24 11:07 UTC214
        request_bytes: usize,
25d14e49ab68atagen2026-09-24 11:07 UTC215
    ) -> Vec<Value> {
25d14e49ab68atagen2026-09-24 11:07 UTC216
        let Some(id) = frame.get(1).and_then(Value::as_str) else {
25d14e49ab68atagen2026-09-24 11:07 UTC217
            return vec![json!(["NOTICE", "REQ requires a subscription id"])];
25d14e49ab68atagen2026-09-24 11:07 UTC218
        };
25d14e49ab68atagen2026-09-24 11:07 UTC219
        if id.len() > 64 {
25d14e49ab68atagen2026-09-24 11:07 UTC220
            return vec![closed(id, "blocked: subscription id is too long")];
25d14e49ab68atagen2026-09-24 11:07 UTC221
        }
25d14e49ab68atagen2026-09-24 11:07 UTC222
        if frame.len() < 3 {
25d14e49ab68atagen2026-09-24 11:07 UTC223
            return vec![closed(id, "blocked: REQ requires a filter")];
25d14e49ab68atagen2026-09-24 11:07 UTC224
        }
25d14e49ab68atagen2026-09-24 11:07 UTC225
        if frame.len() - 2 > self.limits.max_filters {
25d14e49ab68atagen2026-09-24 11:07 UTC226
            return vec![closed(id, "rate-limited: too many filters")];
25d14e49ab68atagen2026-09-24 11:07 UTC227
        }
25d14e49ab68atagen2026-09-24 11:07 UTC228
        if session.subscriptions.len() >= self.limits.max_subscriptions
25d14e49ab68atagen2026-09-24 11:07 UTC229
            && !session.subscriptions.contains_key(id)
25d14e49ab68atagen2026-09-24 11:07 UTC230
        {
25d14e49ab68atagen2026-09-24 11:07 UTC231
            return vec![closed(id, "rate-limited: too many subscriptions")];
25d14e49ab68atagen2026-09-24 11:07 UTC232
        }
25d14e49ab68atagen2026-09-24 11:07 UTC233
        let old_bytes = session.subscriptions.get(id).map_or(0, |entry| entry.bytes);
25d14e49ab68atagen2026-09-24 11:07 UTC234
        let active_bytes = session
25d14e49ab68atagen2026-09-24 11:07 UTC235
            .subscriptions
25d14e49ab68atagen2026-09-24 11:07 UTC236
            .values()
25d14e49ab68atagen2026-09-24 11:07 UTC237
            .map(|entry| entry.bytes)
25d14e49ab68atagen2026-09-24 11:07 UTC238
            .sum::<usize>()
25d14e49ab68atagen2026-09-24 11:07 UTC239
            .saturating_sub(old_bytes);
25d14e49ab68atagen2026-09-24 11:07 UTC240
        let max_subscription_bytes = self
25d14e49ab68atagen2026-09-24 11:07 UTC241
            .limits
25d14e49ab68atagen2026-09-24 11:07 UTC242
            .max_filter_bytes
25d14e49ab68atagen2026-09-24 11:07 UTC243
            .saturating_mul(self.limits.max_subscriptions);
25d14e49ab68atagen2026-09-24 11:07 UTC244
        if active_bytes.saturating_add(request_bytes) > max_subscription_bytes {
25d14e49ab68atagen2026-09-24 11:07 UTC245
            return vec![closed(id, "rate-limited: subscription byte limit exceeded")];
25d14e49ab68atagen2026-09-24 11:07 UTC246
        }
25d14e49ab68atagen2026-09-24 11:07 UTC247
25d14e49ab68atagen2026-09-24 11:07 UTC248
        let mut filters = Vec::with_capacity(frame.len() - 2);
25d14e49ab68atagen2026-09-24 11:07 UTC249
        for value in &frame[2..] {
25d14e49ab68atagen2026-09-24 11:07 UTC250
            let Ok(filter) = serde_json::from_value::<Filter>(value.clone()) else {
25d14e49ab68atagen2026-09-24 11:07 UTC251
                return vec![closed(id, "blocked: invalid filter")];
25d14e49ab68atagen2026-09-24 11:07 UTC252
            };
25d14e49ab68atagen2026-09-24 11:07 UTC253
            match self.policy.admit_query(&filter, &address).await {
25d14e49ab68atagen2026-09-24 11:07 UTC254
                QueryPolicyResult::Accept => filters.push(filter),
25d14e49ab68atagen2026-09-24 11:07 UTC255
                QueryPolicyResult::Reject { prefix, message } => {
25d14e49ab68atagen2026-09-24 11:07 UTC256
                    return vec![closed(id, &format!("{prefix}: {message}"))];
25d14e49ab68atagen2026-09-24 11:07 UTC257
                }
25d14e49ab68atagen2026-09-24 11:07 UTC258
            }
25d14e49ab68atagen2026-09-24 11:07 UTC259
        }
25d14e49ab68atagen2026-09-24 11:07 UTC260
25d14e49ab68atagen2026-09-24 11:07 UTC261
        let mut events = BTreeSet::new();
25d14e49ab68atagen2026-09-24 11:07 UTC262
        for filter in &filters {
25d14e49ab68atagen2026-09-24 11:07 UTC263
            let implicit = filter.limit.is_none();
25d14e49ab68atagen2026-09-24 11:07 UTC264
            let limit = filter.limit.unwrap_or(self.limits.max_query_results);
25d14e49ab68atagen2026-09-24 11:07 UTC265
            let mut query = filter.clone();
25d14e49ab68atagen2026-09-24 11:07 UTC266
            query.limit = Some(if implicit {
25d14e49ab68atagen2026-09-24 11:07 UTC267
                limit.saturating_add(1)
25d14e49ab68atagen2026-09-24 11:07 UTC268
            } else {
25d14e49ab68atagen2026-09-24 11:07 UTC269
                limit
25d14e49ab68atagen2026-09-24 11:07 UTC270
            });
25d14e49ab68atagen2026-09-24 11:07 UTC271
            let found = match self.store.query(query).await {
25d14e49ab68atagen2026-09-24 11:07 UTC272
                Ok(found) => found,
25d14e49ab68atagen2026-09-24 11:07 UTC273
                Err(error) => {
25d14e49ab68atagen2026-09-24 11:07 UTC274
                    let message = if error.to_string().contains("history byte limit exceeded") {
25d14e49ab68atagen2026-09-24 11:07 UTC275
                        "rate-limited: history byte limit exceeded"
25d14e49ab68atagen2026-09-24 11:07 UTC276
                    } else {
25d14e49ab68atagen2026-09-24 11:07 UTC277
                        tracing::error!(%error, "history query failed");
25d14e49ab68atagen2026-09-24 11:07 UTC278
                        "error: database unavailable"
25d14e49ab68atagen2026-09-24 11:07 UTC279
                    };
25d14e49ab68atagen2026-09-24 11:07 UTC280
                    return vec![closed(id, message)];
25d14e49ab68atagen2026-09-24 11:07 UTC281
                }
25d14e49ab68atagen2026-09-24 11:07 UTC282
            };
25d14e49ab68atagen2026-09-24 11:07 UTC283
            if implicit && found.len() > limit {
25d14e49ab68atagen2026-09-24 11:07 UTC284
                return vec![closed(id, "rate-limited: history result limit exceeded")];
25d14e49ab68atagen2026-09-24 11:07 UTC285
            }
25d14e49ab68atagen2026-09-24 11:07 UTC286
            events.extend(found);
25d14e49ab68atagen2026-09-24 11:07 UTC287
            if events.len() > self.limits.max_query_results {
25d14e49ab68atagen2026-09-24 11:07 UTC288
                return vec![closed(id, "rate-limited: too many results")];
25d14e49ab68atagen2026-09-24 11:07 UTC289
            }
25d14e49ab68atagen2026-09-24 11:07 UTC290
        }
25d14e49ab68atagen2026-09-24 11:07 UTC291
        let bytes = events
25d14e49ab68atagen2026-09-24 11:07 UTC292
            .iter()
25d14e49ab68atagen2026-09-24 11:07 UTC293
            .map(|event| event.as_json().len())
25d14e49ab68atagen2026-09-24 11:07 UTC294
            .sum::<usize>();
25d14e49ab68atagen2026-09-24 11:07 UTC295
        if bytes > self.limits.max_query_bytes {
25d14e49ab68atagen2026-09-24 11:07 UTC296
            return vec![closed(id, "rate-limited: history byte limit exceeded")];
25d14e49ab68atagen2026-09-24 11:07 UTC297
        }
25d14e49ab68atagen2026-09-24 11:07 UTC298
25d14e49ab68atagen2026-09-24 11:07 UTC299
        let mut response = Vec::with_capacity(events.len() + 1);
25d14e49ab68atagen2026-09-24 11:07 UTC300
        for event in events {
25d14e49ab68atagen2026-09-24 11:07 UTC301
            if !event.is_expired() {
25d14e49ab68atagen2026-09-24 11:07 UTC302
                response.push(json!(["EVENT", id, event]));
25d14e49ab68atagen2026-09-24 11:07 UTC303
            }
25d14e49ab68atagen2026-09-24 11:07 UTC304
        }
25d14e49ab68atagen2026-09-24 11:07 UTC305
        response.push(json!(["EOSE", id]));
25d14e49ab68atagen2026-09-24 11:07 UTC306
        session.subscriptions.insert(
25d14e49ab68atagen2026-09-24 11:07 UTC307
            id.to_owned(),
25d14e49ab68atagen2026-09-24 11:07 UTC308
            Subscription {
25d14e49ab68atagen2026-09-24 11:07 UTC309
                filters,
25d14e49ab68atagen2026-09-24 11:07 UTC310
                bytes: request_bytes,
25d14e49ab68atagen2026-09-24 11:07 UTC311
            },
25d14e49ab68atagen2026-09-24 11:07 UTC312
        );
25d14e49ab68atagen2026-09-24 11:07 UTC313
        response
25d14e49ab68atagen2026-09-24 11:07 UTC314
    }
25d14e49ab68atagen2026-09-24 11:07 UTC315
}
25d14e49ab68atagen2026-09-24 11:07 UTC316
25d14e49ab68atagen2026-09-24 11:07 UTC317
fn closed(id: &str, message: &str) -> Value {
25d14e49ab68atagen2026-09-24 11:07 UTC318
    json!(["CLOSED", id, message])
25d14e49ab68atagen2026-09-24 11:07 UTC319
}