commit 3dec9757d798553677f82d216ef71158de3610ae
parent d4a0191aeaa8347aed23fee9214d52f49f4bb755
Author: William Casarin <jb55@jb55.com>
Date: Wed, 7 Feb 2024 13:25:36 -0800
subscription: don't let sub lifetimes outlive filters
Since subscriptions don't copy and reference filters in memory
Signed-off-by: William Casarin <jb55@jb55.com>
Diffstat:
4 files changed, 32 insertions(+), 17 deletions(-)
diff --git a/src/filter.rs b/src/filter.rs
@@ -107,6 +107,10 @@ impl Filter {
self.start_tags_field('p');
}
+ fn start_tag_field(&self, tag: char) {
+ unsafe { bindings::ndb_filter_start_tag_field(self.as_mut_ptr(), tag as u8 as c_char) };
+ }
+
fn end_field(&self) {
unsafe { bindings::ndb_filter_end_field(self.as_mut_ptr()) }
}
@@ -120,10 +124,6 @@ impl Filter {
self
}
- fn start_tag_field(&self, tag: char) {
- unsafe { bindings::ndb_filter_start_tag_field(self.as_mut_ptr(), tag as u8 as c_char) };
- }
-
pub fn kinds(self, kinds: Vec<u64>) -> Filter {
self.start_kinds_field();
for kind in kinds {
diff --git a/src/lib.rs b/src/lib.rs
@@ -16,6 +16,7 @@ mod ndb;
mod note;
mod profile;
mod result;
+mod subscription;
mod transaction;
pub use block::{Block, BlockType, Blocks, Mention};
@@ -26,6 +27,7 @@ pub use ndb::Ndb;
pub use note::Note;
pub use profile::ProfileRecord;
pub use result::Result;
+pub use subscription::Subscription;
pub use transaction::Transaction;
mod test_util;
diff --git a/src/ndb.rs b/src/ndb.rs
@@ -2,8 +2,9 @@ use libc;
use std::ffi::CString;
use std::ptr;
-use crate::bindings;
-use crate::{Blocks, Config, Error, Filter, Note, ProfileRecord, Result, Transaction};
+use crate::{
+ bindings, Blocks, Config, Error, Filter, Note, ProfileRecord, Result, Subscription, Transaction,
+};
use std::fs;
use std::os::raw::c_int;
use std::path::Path;
@@ -80,20 +81,21 @@ impl Ndb {
Ok(())
}
- pub fn subscribe(&self, filter: &Filter) -> Result<u64> {
+ pub fn subscribe<'a>(&self, filter: &'a Filter) -> Result<Subscription<'a>> {
unsafe {
- let res = bindings::ndb_subscribe(self.as_ptr(), filter.as_mut_ptr(), 1);
- if res == 0 {
+ let id = bindings::ndb_subscribe(self.as_ptr(), filter.as_mut_ptr(), 1);
+ if id == 0 {
Err(Error::SubscriptionError)
} else {
- Ok(res)
+ Ok(Subscription { filter, id })
}
}
}
- pub fn poll_for_notes(&self, sub_id: u64, max_notes: u32) -> Vec<u64> {
+ pub fn poll_for_notes<'a>(&self, sub: &Subscription<'a>, max_notes: u32) -> Vec<u64> {
let mut vec = vec![];
vec.reserve_exact(max_notes as usize);
+ let sub_id = sub.id;
let res = unsafe {
let res = bindings::ndb_poll_for_notes(
@@ -108,8 +110,13 @@ impl Ndb {
vec
}
- pub async fn wait_for_notes(&self, sub_id: u64, max_notes: u32) -> Result<Vec<u64>> {
+ pub async fn wait_for_notes<'a>(
+ &self,
+ sub: &Subscription<'a>,
+ max_notes: u32,
+ ) -> Result<Vec<u64>> {
let ndb = self.clone();
+ let sub_id = sub.id;
let handle = task::spawn_blocking(move || {
let mut vec = vec![];
vec.reserve_exact(max_notes as usize);
@@ -253,8 +260,8 @@ mod tests {
{
let ndb = Ndb::new(db, &Config::new()).expect("ndb");
let filter = Filter::new().kinds(vec![1]);
- let sub_id = ndb.subscribe(&filter).expect("sub_id");
- let waiter = ndb.wait_for_notes(sub_id, 1);
+ let sub = ndb.subscribe(&filter).expect("sub_id");
+ let waiter = ndb.wait_for_notes(&sub, 1);
ndb.process_event(r#"["EVENT","b",{"id": "702555e52e82cc24ad517ba78c21879f6e47a7c0692b9b20df147916ae8731a3","pubkey": "32bf915904bfde2d136ba45dde32c88f4aca863783999faea2e847a8fafd2f15","created_at": 1702675561,"kind": 1,"tags": [],"content": "hello, world","sig": "2275c5f5417abfd644b7bc74f0388d70feb5d08b6f90fa18655dda5c95d013bfbc5258ea77c05b7e40e0ee51d8a2efa931dc7a0ec1db4c0a94519762c6625675"}]"#).expect("process ok");
let res = waiter.await.expect("await ok");
assert_eq!(res, vec![1]);
@@ -269,15 +276,15 @@ mod tests {
{
let ndb = Ndb::new(db, &Config::new()).expect("ndb");
let filter = Filter::new().kinds(vec![1]);
- let sub_id = ndb.subscribe(&filter).expect("sub_id");
+ let sub = ndb.subscribe(&filter).expect("sub_id");
ndb.process_event(r#"["EVENT","b",{"id": "702555e52e82cc24ad517ba78c21879f6e47a7c0692b9b20df147916ae8731a3","pubkey": "32bf915904bfde2d136ba45dde32c88f4aca863783999faea2e847a8fafd2f15","created_at": 1702675561,"kind": 1,"tags": [],"content": "hello, world","sig": "2275c5f5417abfd644b7bc74f0388d70feb5d08b6f90fa18655dda5c95d013bfbc5258ea77c05b7e40e0ee51d8a2efa931dc7a0ec1db4c0a94519762c6625675"}]"#).expect("process ok");
// this is too fast, we should have nothing
- let res = ndb.poll_for_notes(sub_id, 1);
+ let res = ndb.poll_for_notes(&sub, 1);
assert_eq!(res, vec![]);
std::thread::sleep(std::time::Duration::from_millis(100));
// now we should have something
- let res = ndb.poll_for_notes(sub_id, 1);
+ let res = ndb.poll_for_notes(&sub, 1);
assert_eq!(res, vec![1]);
}
}
diff --git a/src/subscription.rs b/src/subscription.rs
@@ -0,0 +1,6 @@
+use crate::Filter;
+
+pub struct Subscription<'a> {
+ pub filter: &'a Filter,
+ pub id: u64,
+}