Files
eventstore/badger/lib.go
2023-11-09 13:31:24 -03:00

143 lines
2.8 KiB
Go

package badger
import (
"encoding/binary"
"encoding/hex"
"github.com/dgraph-io/badger/v4"
"github.com/fiatjaf/eventstore"
"github.com/nbd-wtf/go-nostr"
)
const (
rawEventStorePrefix byte = 0
indexCreatedAtPrefix byte = 1
indexIdPrefix byte = 2
indexKindPrefix byte = 3
indexPubkeyPrefix byte = 4
indexPubkeyKindPrefix byte = 5
indexTagPrefix byte = 6
)
var _ eventstore.Store = (*BadgerBackend)(nil)
type BadgerBackend struct {
Path string
MaxLimit int
*badger.DB
seq *badger.Sequence
}
func (b *BadgerBackend) Init() error {
db, err := badger.Open(badger.DefaultOptions(b.Path))
if err != nil {
return err
}
b.DB = db
b.seq, err = db.GetSequence([]byte("events"), 1000)
if err != nil {
return err
}
if b.MaxLimit == 0 {
b.MaxLimit = 500
}
return nil
}
func (b BadgerBackend) Close() {
b.DB.Close()
b.seq.Release()
}
func (b BadgerBackend) Serial() []byte {
v, _ := b.seq.Next()
vb := make([]byte, 5)
vb[0] = rawEventStorePrefix
binary.BigEndian.PutUint32(vb[1:], uint32(v))
return vb
}
func getIndexKeysForEvent(evt *nostr.Event, idx []byte) [][]byte {
keys := make([][]byte, 0, 18)
// indexes
{
// ~ by id
id, _ := hex.DecodeString(evt.ID)
k := make([]byte, 1+32+4)
k[0] = indexIdPrefix
copy(k[1:], id)
copy(k[1+32:], idx)
keys = append(keys, k)
}
{
// ~ by pubkey+date
pubkey, _ := hex.DecodeString(evt.PubKey)
k := make([]byte, 1+32+4+4)
k[0] = indexPubkeyPrefix
copy(k[1:], pubkey)
binary.BigEndian.PutUint32(k[1+32:], uint32(evt.CreatedAt))
copy(k[1+32+4:], idx)
keys = append(keys, k)
}
{
// ~ by kind+date
k := make([]byte, 1+2+4+4)
k[0] = indexKindPrefix
binary.BigEndian.PutUint16(k[1:], uint16(evt.Kind))
binary.BigEndian.PutUint32(k[1+2:], uint32(evt.CreatedAt))
copy(k[1+2+4:], idx)
keys = append(keys, k)
}
{
// ~ by pubkey+kind+date
pubkey, _ := hex.DecodeString(evt.PubKey)
k := make([]byte, 1+32+2+4+4)
k[0] = indexPubkeyKindPrefix
copy(k[1:], pubkey)
binary.BigEndian.PutUint16(k[1+32:], uint16(evt.Kind))
binary.BigEndian.PutUint32(k[1+32+2:], uint32(evt.CreatedAt))
copy(k[1+32+2+4:], idx)
keys = append(keys, k)
}
// ~ by tagvalue+date
for _, tag := range evt.Tags {
if len(tag) < 2 || len(tag[0]) != 1 || len(tag[1]) == 0 || len(tag[1]) > 100 {
continue
}
var v []byte
if vb, _ := hex.DecodeString(tag[1]); len(vb) == 32 {
// store value as bytes
v = vb
} else {
v = []byte(tag[1])
}
k := make([]byte, 1+len(v)+4+4)
k[0] = indexTagPrefix
copy(k[1:], v)
binary.BigEndian.PutUint32(k[1+len(v):], uint32(evt.CreatedAt))
copy(k[1+len(v)+4:], idx)
keys = append(keys, k)
}
{
// ~ by date only
k := make([]byte, 1+4+4)
k[0] = indexCreatedAtPrefix
binary.BigEndian.PutUint32(k[1:], uint32(evt.CreatedAt))
copy(k[1+4:], idx)
keys = append(keys, k)
}
return keys
}