Skip to content

Commit c1a785d

Browse files
committed
migration: migrate full reaction stats for all kind1 notes
Signed-off-by: William Casarin <[email protected]>
1 parent b81490c commit c1a785d

File tree

6 files changed

+143
-36
lines changed

6 files changed

+143
-36
lines changed

TODO

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1 @@
11
test write +metadata
2-
(B) migrate reply stats +metadata
3-
(B) migrate quote stats +metadata
4-
(B) migrate reaction stats +metadata

ndb.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ static int usage()
2828
printf(" print-tag-keys\n");
2929
printf(" print-relay-kind-index-keys\n");
3030
printf(" print-author-kind-index-keys\n");
31+
printf(" print-note-metadata\n");
3132
printf(" import <line-delimited json file>\n\n");
3233

3334
printf("settings\n\n");
@@ -108,6 +109,7 @@ int ndb_print_kind_keys(struct ndb_txn *txn);
108109
int ndb_print_tag_index(struct ndb_txn *txn);
109110
int ndb_print_relay_kind_index(struct ndb_txn *txn);
110111
int ndb_print_author_kind_index(struct ndb_txn *txn);
112+
int ndb_print_note_metadata(struct ndb_txn *txn);
111113

112114
static void print_note(struct ndb_note *note)
113115
{
@@ -443,6 +445,10 @@ int main(int argc, char *argv[])
443445
ndb_begin_query(ndb, &txn);
444446
ndb_print_author_kind_index(&txn);
445447
ndb_end_query(&txn);
448+
} else if (argc == 2 && !strcmp(argv[1], "print-note-metadata")) {
449+
ndb_begin_query(ndb, &txn);
450+
ndb_print_note_metadata(&txn);
451+
ndb_end_query(&txn);
446452
} else if (argc == 3 && !strcmp(argv[1], "note-relays")) {
447453
struct ndb_note_relay_iterator iter;
448454
const char *relay;

src/metadata.c

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ uint16_t *ndb_note_meta_entry_type(struct ndb_note_meta_entry *entry)
221221
}
222222

223223
/* find a metadata entry, optionally matching a payload */
224-
struct ndb_note_meta_entry *ndb_note_meta_find_entry(struct ndb_note_meta *meta, uint16_t type, uint64_t *payload)
224+
static struct ndb_note_meta_entry *ndb_note_meta_find_entry_impl(struct ndb_note_meta *meta, uint16_t type, uint64_t *payload, int sorted)
225225
{
226226
struct ndb_note_meta_entry *entries, *entry;
227227
int i;
@@ -232,6 +232,8 @@ struct ndb_note_meta_entry *ndb_note_meta_find_entry(struct ndb_note_meta *meta,
232232
entries = ndb_note_meta_entries(meta);
233233
assert(((intptr_t)entries - (intptr_t)meta) == 16);
234234

235+
/* TODO(jb55): do bsearch for large sorted entries */
236+
235237
for (i = 0; i < meta->count; i++) {
236238
entry = &entries[i];
237239
assert(((uintptr_t)entry % 8) == 0);
@@ -250,6 +252,22 @@ struct ndb_note_meta_entry *ndb_note_meta_find_entry(struct ndb_note_meta *meta,
250252
return NULL;
251253
}
252254

255+
struct ndb_note_meta_entry *ndb_note_meta_find_entry(struct ndb_note_meta *meta, uint16_t type, uint64_t *payload)
256+
{
257+
int sorted = 1;
258+
return ndb_note_meta_find_entry_impl(meta, type, payload, sorted);
259+
}
260+
261+
struct ndb_note_meta_entry *ndb_note_meta_builder_find_entry(
262+
struct ndb_note_meta_builder *builder,
263+
uint16_t type,
264+
uint64_t *payload)
265+
{
266+
/* meta building in progress is not necessarily sorted */
267+
int sorted = 0;
268+
return ndb_note_meta_find_entry_impl((struct ndb_note_meta *)builder->cursor.start, type, payload, sorted);
269+
}
270+
253271
void ndb_note_meta_reaction_set(struct ndb_note_meta_entry *entry, uint32_t count, union ndb_reaction_str str)
254272
{
255273
entry->type = NDB_NOTE_META_REACTION;
@@ -389,3 +407,35 @@ union ndb_reaction_str ndb_note_meta_reaction_str(struct ndb_note_meta_entry *en
389407
{
390408
return entry->payload.reaction_str;
391409
}
410+
411+
void print_note_meta(struct ndb_note_meta *meta)
412+
{
413+
int count, i;
414+
struct ndb_note_meta_entry *entries, *entry;
415+
union ndb_reaction_str reaction;
416+
char strbuf[128];
417+
418+
count = ndb_note_meta_entries_count(meta);
419+
entries = ndb_note_meta_entries(meta);
420+
421+
for (i = 0; i < count; i++) {
422+
entry = &entries[i];
423+
switch (entry->type) {
424+
case NDB_NOTE_META_REACTION:
425+
reaction = ndb_note_meta_reaction_str(entry);
426+
427+
ndb_reaction_to_str(&reaction, strbuf);
428+
printf("%s%d ", strbuf, *ndb_note_meta_reaction_count(entry));
429+
break;
430+
case NDB_NOTE_META_COUNTS:
431+
printf("quotes %d\treplies %d\tall_replies %d\treactions %d\t",
432+
*ndb_note_meta_counts_quotes(entry),
433+
*ndb_note_meta_counts_direct_replies(entry),
434+
*ndb_note_meta_counts_thread_replies(entry),
435+
*ndb_note_meta_counts_total_reactions(entry));
436+
break;
437+
}
438+
}
439+
440+
printf("\n");
441+
}

src/nostrdb.c

Lines changed: 80 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2178,7 +2178,7 @@ int ndb_count_replies(struct ndb_txn *txn, const unsigned char *note_id, uint16_
21782178
}
21792179

21802180
/* count all of the reactions for a note */
2181-
int ndb_count_reactions(struct ndb_txn *txn, const unsigned char *note_id, uint32_t *count)
2181+
int ndb_rebuild_reaction_metadata(struct ndb_txn *txn, const unsigned char *note_id, struct ndb_note_meta_builder *builder, uint32_t *count)
21822182
{
21832183
MDB_val k, v;
21842184
MDB_cursor *cur;
@@ -2189,6 +2189,8 @@ int ndb_count_reactions(struct ndb_txn *txn, const unsigned char *note_id, uint3
21892189
size_t size;
21902190
struct ndb_note *note;
21912191
unsigned char *keybuf, *last_id;
2192+
struct ndb_note_meta_entry *entry;
2193+
union ndb_reaction_str reaction_str;
21922194
char buffer[41]; /* 1 + 32 + 8 */
21932195
*count = 0;
21942196

@@ -2227,6 +2229,21 @@ int ndb_count_reactions(struct ndb_txn *txn, const unsigned char *note_id, uint3
22272229
continue;
22282230
if (memcmp(last_id, note_id, 32))
22292231
continue;
2232+
2233+
if (builder) {
2234+
if (!ndb_reaction_set(&reaction_str, ndb_note_content(note)))
2235+
ndb_reaction_set(&reaction_str, "+");
2236+
2237+
if ((entry = ndb_note_meta_builder_find_entry(builder, NDB_NOTE_META_REACTION, &reaction_str.binmoji))) {
2238+
(*ndb_note_meta_reaction_count(entry))++;
2239+
} else if ((entry = ndb_note_meta_add_entry(builder))) {
2240+
ndb_note_meta_reaction_set(entry, 1, reaction_str);
2241+
} else {
2242+
/* couldn't add reaction entry ? */
2243+
ndb_debug("ndb_rebuild_note_indices: couldn't add reaction count entry to metadata builder\n");
2244+
}
2245+
}
2246+
22302247
(*count)++;
22312248
} while (mdb_cursor_get(cur, &k, &v, MDB_NEXT) == 0);
22322249

@@ -2301,19 +2318,22 @@ static int ndb_note_meta_builder_counts(struct ndb_txn *txn,
23012318
thread_replies = 0;
23022319
total_reactions = 0;
23032320

2304-
if (!(entry = ndb_note_meta_add_entry(builder)))
2305-
return 0;
2306-
2307-
rcs[0] = ndb_count_reactions(txn, note_id, &total_reactions);
2321+
rcs[0] = ndb_rebuild_reaction_metadata(txn, note_id, builder, &total_reactions);
23082322
rcs[1] = ndb_count_quotes(txn, note_id, &quotes);
23092323
rcs[2] = ndb_count_replies(txn, note_id, &direct_replies, &thread_replies);
23102324

2311-
if (!rcs[0] && !rcs[1] && !rcs[2])
2325+
if (!rcs[0] && !rcs[1] && !rcs[2]) {
23122326
return 0;
2327+
}
23132328

23142329
/* no entry needed */
2315-
if (quotes == 0 && direct_replies == 0 && thread_replies == 0 && quotes == 0)
2316-
return 1;
2330+
if (quotes == 0 && direct_replies == 0 && thread_replies == 0 && quotes == 0) {
2331+
return 0;
2332+
}
2333+
2334+
if (!(entry = ndb_note_meta_add_entry(builder))) {
2335+
return 0;
2336+
}
23172337

23182338
ndb_note_meta_counts_set(entry, total_reactions, quotes, direct_replies, thread_replies);
23192339

@@ -2334,49 +2354,58 @@ static int ndb_migrate_metadata(struct ndb_txn *txn)
23342354
{
23352355
MDB_val k, k2, v, v2;
23362356
MDB_cursor *cur;
2337-
MDB_dbi db;
2357+
MDB_dbi note_db, meta_db;
23382358
unsigned char *id;
2339-
unsigned char buffer[4096];
2340-
int rc;
2359+
size_t scratch_size = 1024 * 1024;
2360+
unsigned char *buffer = malloc(scratch_size);
2361+
int rc, count;
23412362
struct ndb_note_meta_builder builder;
2363+
struct ndb_note *note;
23422364
struct ndb_note_meta *meta;
23432365

2344-
db = txn->lmdb->dbs[NDB_DB_META];
2366+
meta_db = txn->lmdb->dbs[NDB_DB_META];
2367+
note_db = txn->lmdb->dbs[NDB_DB_NOTE];
23452368

2346-
if ((rc = mdb_cursor_open(txn->mdb_txn, db, &cur))) {
2369+
if ((rc = mdb_cursor_open(txn->mdb_txn, note_db, &cur))) {
23472370
fprintf(stderr, "ndb_migrate_reaction_stats: mdb_cursor_open failed, error %d\n", rc);
23482371
return -1;
23492372
}
23502373

2374+
count = 0;
2375+
23512376
/* loop through every metadata entry */
23522377
while (mdb_cursor_get(cur, &k, &v, MDB_NEXT) == 0) {
2353-
ndb_note_meta_builder_init(&builder, buffer, sizeof(buffer));
2378+
ndb_note_meta_builder_init(&builder, buffer, scratch_size);
23542379

2355-
id = (unsigned char *)k.mv_data;
2356-
ndb_note_meta_builder_count_reactions(txn, &builder);
2357-
ndb_note_meta_builder_counts(txn, id, &builder);
2358-
ndb_note_meta_build(&builder, &meta);
2380+
note = (struct ndb_note *)v.mv_data;
2381+
id = ndb_note_id(note);
2382+
k2.mv_data = (unsigned char *)id;
2383+
k2.mv_size = 32;
23592384

2360-
/* no counts found, just delete this entry */
2361-
if (ndb_note_meta_entries_count(meta) == 0) {
2362-
if ((rc = mdb_del(txn->mdb_txn, db, &k, &v))) {
2363-
ndb_debug("delete old metadata entry failed: %s\n", mdb_strerror(rc));
2364-
return -1;
2365-
}
2385+
rc = ndb_note_meta_builder_counts(txn, id, &builder);
2386+
if (!rc) {
2387+
mdb_del(txn->mdb_txn, meta_db, &k2, NULL);
23662388
continue;
23672389
}
23682390

2369-
k2.mv_data = (unsigned char *)id;
2370-
k2.mv_size = 32;
2391+
ndb_note_meta_build(&builder, &meta);
2392+
assert(ndb_note_meta_entries(meta)->type != 0);
2393+
23712394
v2.mv_data = meta;
23722395
v2.mv_size = ndb_note_meta_total_size(meta);
23732396

23742397
/* set entry */
2375-
if ((rc = mdb_put(txn->mdb_txn, db, &k2, &v2, 0))) {
2398+
if ((rc = mdb_put(txn->mdb_txn, meta_db, &k2, &v2, 0))) {
23762399
ndb_debug("migrate metadata entry failed on write: %s\n", mdb_strerror(rc));
23772400
}
2401+
2402+
count++;
23782403
}
23792404

2405+
fprintf(stderr, "nostrdb: migrated %d metadata entries\n", count);
2406+
2407+
free(buffer);
2408+
mdb_cursor_close(cur);
23802409
return 1;
23812410
}
23822411

@@ -2713,7 +2742,7 @@ static struct ndb_migration MIGRATIONS[] = {
27132742
{ .fn = ndb_migrate_lower_user_search_indices },
27142743
{ .fn = ndb_migrate_utf8_profile_names },
27152744
{ .fn = ndb_migrate_profile_indices },
2716-
//{ .fn = ndb_migrate_metadata },
2745+
{ .fn = ndb_migrate_metadata },
27172746
};
27182747

27192748

@@ -8515,6 +8544,29 @@ void ndb_config_set_ingest_filter(struct ndb_config *config,
85158544
config->filter_context = filter_ctx;
85168545
}
85178546

8547+
int ndb_print_note_metadata(struct ndb_txn *txn)
8548+
{
8549+
MDB_cursor *cur;
8550+
MDB_val k, v;
8551+
int i;
8552+
8553+
if (mdb_cursor_open(txn->mdb_txn, txn->lmdb->dbs[NDB_DB_META], &cur))
8554+
return 0;
8555+
8556+
i = 1;
8557+
while (mdb_cursor_get(cur, &k, &v, MDB_NEXT) == 0) {
8558+
print_hex(k.mv_data, 32);
8559+
printf("\t");
8560+
print_note_meta((struct ndb_note_meta*)v.mv_data);
8561+
i++;
8562+
}
8563+
8564+
mdb_cursor_close(cur);
8565+
8566+
return i;
8567+
}
8568+
8569+
85188570
int ndb_print_author_kind_index(struct ndb_txn *txn)
85198571
{
85208572
MDB_cursor *cur;

src/nostrdb.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ struct bolt11;
4949
*/
5050
enum ndb_metadata_type {
5151
NDB_NOTE_META_RESERVED = 0, /* not used */
52-
NDB_NOTE_META_COUNTS = 2, /* replies, quotes, etc */
53-
NDB_NOTE_META_REACTION = 4, /* count of all the reactions on a post, grouped by different reaction strings */
52+
NDB_NOTE_META_COUNTS = 100, /* replies, quotes, etc */
53+
NDB_NOTE_META_REACTION = 200, /* count of all the reactions on a post, grouped by different reaction strings */
5454
};
5555

5656
// some bindings like swift needs help with forward declared pointers
@@ -658,6 +658,7 @@ struct ndb_note_meta *ndb_get_note_meta(struct ndb_txn *txn, const unsigned char
658658
int ndb_set_note_meta(struct ndb *ndb, const unsigned char *id, struct ndb_note_meta *meta);
659659
size_t ndb_note_meta_total_size(struct ndb_note_meta *header);
660660
int ndb_note_meta_builder_init(struct ndb_note_meta_builder *builder, unsigned char *, size_t);
661+
struct ndb_note_meta_entry *ndb_note_meta_builder_find_entry(struct ndb_note_meta_builder *builder, uint16_t type, uint64_t *payload);
661662
void ndb_note_meta_build(struct ndb_note_meta_builder *builder, struct ndb_note_meta **meta);
662663
uint16_t ndb_note_meta_entries_count(struct ndb_note_meta *meta);
663664
struct ndb_note_meta_entry *ndb_note_meta_entries(struct ndb_note_meta *meta);
@@ -673,6 +674,7 @@ uint16_t *ndb_note_meta_counts_direct_replies(struct ndb_note_meta_entry *entry)
673674
uint32_t *ndb_note_meta_counts_thread_replies(struct ndb_note_meta_entry *entry);
674675
uint16_t *ndb_note_meta_entry_type(struct ndb_note_meta_entry *entry);
675676
struct ndb_note_meta_entry *ndb_note_meta_entry_at(struct ndb_note_meta *meta, int ind);
677+
void print_note_meta(struct ndb_note_meta *meta);
676678

677679
// META STRINGS
678680
int ndb_reaction_set(union ndb_reaction_str *reaction, const char *str);

test.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ static void delete_test_db() {
3030
unlink(TEST_DIR "/data.lock");
3131
}
3232

33-
int ndb_count_reactions(struct ndb_txn *txn, const unsigned char *note_id, uint32_t *count);
33+
int ndb_rebuild_reaction_metadata(struct ndb_txn *txn, const unsigned char *note_id, struct ndb_note_meta_builder *builder, uint32_t *count);
3434
int ndb_count_replies(struct ndb_txn *txn, const unsigned char *note_id, uint16_t *direct_replies, uint32_t *thread_replies);
3535

3636
static void db_load_events(struct ndb *ndb, const char *filename)
@@ -141,7 +141,7 @@ static void test_count_metadata()
141141
ndb_begin_query(ndb, &txn);
142142
/* this is used in the migration code,
143143
* let's make sure it matches the online logic */
144-
ndb_count_reactions(&txn, id, &reactions);
144+
ndb_rebuild_reaction_metadata(&txn, id, NULL, &reactions);
145145
printf("\t# after-counted reactions %d\n", reactions);
146146
assert(reactions == total_reactions);
147147

0 commit comments

Comments
 (0)