boltdb support.
This commit is contained in:
114
bolt/helpers.go
Normal file
114
bolt/helpers.go
Normal file
@@ -0,0 +1,114 @@
|
||||
package bolt
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
|
||||
"github.com/fiatjaf/eventstore"
|
||||
"github.com/nbd-wtf/go-nostr"
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
||||
// returns
|
||||
// - the bucket id where this will be saved
|
||||
// - the key with full length for created_at and idx at the end, but not filled with these
|
||||
// - the offset -- i.e. where the prefix ends and the created_at and idx would start
|
||||
func getTagIndexPrefix(tagValue string) (bucket []byte, key []byte, offset int) {
|
||||
if kind, pkb, d := eventstore.GetAddrTagElements(tagValue); len(pkb) == 32 {
|
||||
// store value in the new special "a" tag index
|
||||
key = make([]byte, 2+8+len(d)+4)
|
||||
binary.BigEndian.PutUint16(key[1:], kind)
|
||||
copy(key[2:], pkb[0:8])
|
||||
copy(key[2+8:], d)
|
||||
offset = 2 + 8 + len(d)
|
||||
bucket = bucketTagAddr
|
||||
} else if vb, _ := hex.DecodeString(tagValue); len(vb) == 32 {
|
||||
// store value as bytes
|
||||
key = make([]byte, 8+4)
|
||||
copy(key, vb[0:8])
|
||||
offset = 8
|
||||
bucket = bucketTag32
|
||||
} else {
|
||||
// store whatever as utf-8
|
||||
key = make([]byte, len(tagValue)+4)
|
||||
copy(key, tagValue)
|
||||
offset = len(tagValue)
|
||||
bucket = bucketTag
|
||||
}
|
||||
|
||||
return bucket, key, offset
|
||||
}
|
||||
|
||||
type keymeta struct {
|
||||
bucket []byte
|
||||
key []byte
|
||||
}
|
||||
|
||||
func getIndexKeysForEvent(evt *nostr.Event) []keymeta {
|
||||
keys := make([]keymeta, 0, 24)
|
||||
|
||||
// indexes
|
||||
{
|
||||
// ~ by id
|
||||
idPrefix8, _ := hex.DecodeString(evt.ID[0 : 8*2])
|
||||
k := idPrefix8
|
||||
keys = append(keys, keymeta{bucket: bucketId, key: k})
|
||||
}
|
||||
|
||||
{
|
||||
// ~ by pubkey+date
|
||||
pubkeyPrefix8, _ := hex.DecodeString(evt.PubKey[0 : 8*2])
|
||||
k := make([]byte, 8+4)
|
||||
copy(k[:], pubkeyPrefix8)
|
||||
binary.BigEndian.PutUint32(k[8:], uint32(evt.CreatedAt))
|
||||
keys = append(keys, keymeta{bucket: bucketPubkey, key: k})
|
||||
}
|
||||
|
||||
{
|
||||
// ~ by kind+date
|
||||
k := make([]byte, 2+4)
|
||||
binary.BigEndian.PutUint16(k[:], uint16(evt.Kind))
|
||||
binary.BigEndian.PutUint32(k[2:], uint32(evt.CreatedAt))
|
||||
keys = append(keys, keymeta{bucket: bucketKind, key: k})
|
||||
}
|
||||
|
||||
{
|
||||
// ~ by pubkey+kind+date
|
||||
pubkeyPrefix8, _ := hex.DecodeString(evt.PubKey[0 : 8*2])
|
||||
k := make([]byte, 8+2+4)
|
||||
copy(k[:], pubkeyPrefix8)
|
||||
binary.BigEndian.PutUint16(k[8:], uint16(evt.Kind))
|
||||
binary.BigEndian.PutUint32(k[8+2:], uint32(evt.CreatedAt))
|
||||
keys = append(keys, keymeta{bucket: bucketPubkeyKind, key: k})
|
||||
}
|
||||
|
||||
// ~ by tagvalue+date
|
||||
for i, tag := range evt.Tags {
|
||||
if len(tag) < 2 || len(tag[0]) != 1 || len(tag[1]) == 0 || len(tag[1]) > 100 {
|
||||
// not indexable
|
||||
continue
|
||||
}
|
||||
firstIndex := slices.IndexFunc(evt.Tags, func(t nostr.Tag) bool { return len(t) >= 2 && t[1] == tag[1] })
|
||||
if firstIndex != i {
|
||||
// duplicate
|
||||
continue
|
||||
}
|
||||
|
||||
// get key prefix (with full length) and offset where to write the created_at
|
||||
bucket, k, offset := getTagIndexPrefix(tag[1])
|
||||
|
||||
// write the created_at
|
||||
binary.BigEndian.PutUint32(k[offset:], uint32(evt.CreatedAt))
|
||||
|
||||
keys = append(keys, keymeta{bucket: bucket, key: k})
|
||||
}
|
||||
|
||||
{
|
||||
// ~ by date only
|
||||
k := make([]byte, 4)
|
||||
binary.BigEndian.PutUint32(k[:], uint32(evt.CreatedAt))
|
||||
keys = append(keys, keymeta{bucket: bucketCreatedAt, key: k})
|
||||
}
|
||||
|
||||
return keys
|
||||
}
|
||||
Reference in New Issue
Block a user