Skip to content

Commit 14d7f2b

Browse files
committed
metadata: initial docs and remaining TODO
Signed-off-by: William Casarin <[email protected]>
1 parent 0884aea commit 14d7f2b

File tree

2 files changed

+90
-0
lines changed

2 files changed

+90
-0
lines changed

TODO

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
implement NDB_WRITER_NOTE_META
2+
test write metadata

docs/metadata.md

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
2+
# Note Metadata
3+
4+
nostrdb supports a flexible metadata system which allows you to store additional information about a nostr note.
5+
6+
metadata is stored as a sorted list of TVs (tag, value). The lengths are a fixed size but can reference a data table.
7+
8+
The type follows the "it's ok to be odd" rule. odd tags are opaque, user defined types that can store data of any kind.
9+
10+
## Binary format
11+
12+
The binary format starts with a header containing the number of metadata entries. The count is followed by a sorted, aligned list of these entries:
13+
14+
```c
15+
16+
// 16 bytes
17+
struct ndb_note_meta {
18+
// 4 bytes
19+
uint8_t version;
20+
uint8_t padding[3];
21+
uint16_t count;
22+
23+
// 4 bytes
24+
uint32_t data_table_size;
25+
26+
// 8 bytes
27+
uint64_t flags;
28+
}
29+
30+
31+
// 16 bytes
32+
struct ndb_note_meta_entry {
33+
// 4 byte entry header
34+
uint16_t type;
35+
uint16_t flags;
36+
37+
// additional 4 bytes of aux storage for payloads that are >8 bytes
38+
//
39+
// for reactions types, this is used for counts
40+
// normally this would have been padding but we make use of it
41+
// in our manually packed structure
42+
//
43+
uint32_t aux;
44+
45+
// 8 byte metadata payload
46+
union {
47+
struct {
48+
uint32_t offset;
49+
uint32_t padding;
50+
} offset;
51+
52+
// the reaction binmoji[1] for reaction, count is stored in aux
53+
union ndb_reaction_str reaction_str;
54+
} payload;
55+
}
56+
57+
// types, standard types are multiplied by 2, since odd
58+
// types are user defined. We explicity multiply by
59+
// two in the enum to be unambiguous
60+
enum metadata_type {
61+
NDB_NOTE_META_RESERVED = 0,
62+
NDB_NOTE_META_REACTION = 2,
63+
}
64+
65+
```
66+
67+
The offset is to a chunk of potentially unaligned data:
68+
69+
```
70+
size : varint
71+
data : u8[size]
72+
```
73+
74+
### Rationale
75+
76+
We want the following properties:
77+
78+
* The ability to quickly iterate/skip over different metadata fields. This is achieved by a fixed table format, without needing to encode/decode like blocks
79+
* The ability to quickly update metadata fields. To update flags or counts can be done via race-safe mutation operations. The mutation can be done inplace (memcpy + poke memory address)
80+
* The table entries can be inplace sorted for binary search lookups on large metadata tables
81+
82+
## Write thread mutation operations
83+
84+
We want to support many common operations:
85+
86+
* Increase reaction count for a specific reaction type
87+
88+
[binmoji]: https://github.com/jb55/binmoji

0 commit comments

Comments
 (0)