commit aac9e1749b3a3f52251d4cd5ba88766c76beb4c1
parent 565e6895915d187fcbb9c05c90895dea4363b8f5
Author: William Casarin <jb55@jb55.com>
Date: Thu, 20 Mar 2025 13:37:23 -0700
relay: add note relay iteration
This is a simple cursor that walks the NDB_DB_NOTE_RELAYS db
Signed-off-by: William Casarin <jb55@jb55.com>
Diffstat:
3 files changed, 89 insertions(+), 6 deletions(-)
diff --git a/src/nostrdb.c b/src/nostrdb.c
@@ -7328,6 +7328,57 @@ struct ndb_note * ndb_note_from_bytes(unsigned char *bytes)
return note;
}
+int ndb_note_relay_iterate_start(struct ndb_txn *txn,
+ struct ndb_note_relay_iterator *iter,
+ uint64_t note_key)
+{
+ if (mdb_cursor_open(txn->mdb_txn, txn->lmdb->dbs[NDB_DB_NOTE_RELAYS],
+ (MDB_cursor**)&iter->mdb_cur)) {
+ return 0;
+ }
+
+ iter->txn = txn;
+ iter->cursor_op = MDB_SET_KEY;
+ iter->note_key = note_key;
+
+ return 1;
+}
+
+const char *ndb_note_relay_iterate_next(struct ndb_note_relay_iterator *iter)
+{
+ int rc;
+ MDB_val k, v;
+
+ if (iter->mdb_cur == NULL)
+ return NULL;
+
+ k.mv_data = &iter->note_key;
+ k.mv_size = sizeof(iter->note_key);
+
+ if ((rc = mdb_cursor_get((MDB_cursor *)iter->mdb_cur, &k, &v,
+ (MDB_cursor_op)iter->cursor_op)))
+ {
+ //fprintf(stderr, "autoclosing %d '%s'\n", iter->cursor_op, mdb_strerror(rc));
+ // autoclose
+ ndb_note_relay_iterate_close(iter);
+ return NULL;
+ }
+
+ iter->cursor_op = MDB_NEXT_DUP;
+
+ return (const char*)v.mv_data;
+}
+
+void ndb_note_relay_iterate_close(struct ndb_note_relay_iterator *iter)
+{
+ if (!iter || iter->mdb_cur == NULL)
+ return;
+
+ mdb_cursor_close((MDB_cursor*)iter->mdb_cur);
+
+ iter->mdb_cur = NULL;
+}
+
void ndb_tags_iterate_start(struct ndb_note *note, struct ndb_iterator *iter)
{
iter->note = note;
diff --git a/src/nostrdb.h b/src/nostrdb.h
@@ -229,6 +229,13 @@ struct ndb_builder {
struct ndb_tag *current_tag;
};
+struct ndb_note_relay_iterator {
+ struct ndb_txn *txn;
+ uint64_t note_key;
+ int cursor_op;
+ void *mdb_cur;
+};
+
struct ndb_iterator {
struct ndb_note *note;
struct ndb_tag *tag;
@@ -610,6 +617,11 @@ int ndb_tags_iterate_next(struct ndb_iterator *iter);
struct ndb_str ndb_iter_tag_str(struct ndb_iterator *iter, int ind);
struct ndb_str ndb_tag_str(struct ndb_note *note, struct ndb_tag *tag, int ind);
+// RELAY ITER
+int ndb_note_relay_iterate_start(struct ndb_txn *txn, struct ndb_note_relay_iterator *iter, uint64_t note_key);
+const char *ndb_note_relay_iterate_next(struct ndb_note_relay_iterator *iter);
+void ndb_note_relay_iterate_close(struct ndb_note_relay_iterator *iter);
+
// NAMES
const char *ndb_db_name(enum ndb_dbs db);
const char *ndb_kind_name(enum ndb_common_kind ck);
diff --git a/test.c b/test.c
@@ -1781,12 +1781,13 @@ static void test_filter_parse_search_json() {
static void test_note_relay_index()
{
+ const char *relay;
struct ndb *ndb;
struct ndb_txn txn;
struct ndb_config config;
struct ndb_note *note;
struct ndb_filter filter, *f = &filter;
- uint64_t note_id, subid;
+ uint64_t note_key, subid;
struct ndb_ingest_meta meta;
const char *json = "[\"EVENT\",{\"id\": \"0f20295584a62d983a4fa85f7e50b460cd0049f94d8cd250b864bb822a747114\",\"pubkey\": \"55c882cf4a255ac66fc8507e718a1d1283ba46eb7d678d0573184dada1a4f376\",\"created_at\": 1742498339,\"kind\": 1,\"tags\": [],\"content\": \"hi\",\"sig\": \"ae1218280f554ea0b04ae09921031493d60fb7831dfd2dbd7086efeace2719a46842ce80342ebc002da8943df02e98b8b4abb4629c7103ca2114e6c4425f97fe\"}]";
@@ -1809,11 +1810,11 @@ static void test_note_relay_index()
ndb_ingest_meta_init(&meta, 1, "wss://relay.damus.io");
assert(ndb_process_event_with(ndb, json, strlen(json), &meta));
- assert(ndb_wait_for_notes(ndb, subid, ¬e_id, 1) == 1);
- assert(note_id > 0);
+ assert(ndb_wait_for_notes(ndb, subid, ¬e_key, 1) == 1);
+ assert(note_key > 0);
assert(ndb_begin_query(ndb, &txn));
- assert((note = ndb_get_note_by_key(&txn, note_id, NULL)));
+ assert((note = ndb_get_note_by_key(&txn, note_key, NULL)));
ndb_end_query(&txn);
@@ -1826,8 +1827,27 @@ static void test_note_relay_index()
// 4) Check that we have both relays
assert(ndb_begin_query(ndb, &txn));
- assert(ndb_note_seen_on_relay(&txn, note_id, "wss://relay.damus.io"));
- assert(ndb_note_seen_on_relay(&txn, note_id, "wss://relay.mit.edu"));
+ assert(ndb_note_seen_on_relay(&txn, note_key, "wss://relay.damus.io"));
+ assert(ndb_note_seen_on_relay(&txn, note_key, "wss://relay.mit.edu"));
+
+ // walk the relays
+ struct ndb_note_relay_iterator iter;
+
+ assert(ndb_note_relay_iterate_start(&txn, &iter, note_key));
+
+ relay = ndb_note_relay_iterate_next(&iter);
+ assert(relay);
+ assert(!strcmp(relay, "wss://relay.damus.io"));
+
+ relay = ndb_note_relay_iterate_next(&iter);
+ assert(relay);
+ assert(!strcmp(relay, "wss://relay.mit.edu"));
+
+ assert(ndb_note_relay_iterate_next(&iter) == NULL);
+ ndb_note_relay_iterate_close(&iter);
+ assert(iter.mdb_cur == NULL);
+
+ assert(ndb_end_query(&txn));
// Cleanup
ndb_destroy(ndb);