101 lines
2.0 KiB
Go
101 lines
2.0 KiB
Go
package badger
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"fmt"
|
|
"sync/atomic"
|
|
|
|
"fiatjaf.com/nostr"
|
|
"fiatjaf.com/nostr/eventstore"
|
|
"github.com/dgraph-io/badger/v4"
|
|
)
|
|
|
|
const (
|
|
dbVersionKey byte = 255
|
|
rawEventStorePrefix byte = 0
|
|
indexCreatedAtPrefix byte = 1
|
|
indexIdPrefix byte = 2
|
|
indexKindPrefix byte = 3
|
|
indexPubkeyPrefix byte = 4
|
|
indexPubkeyKindPrefix byte = 5
|
|
indexTagPrefix byte = 6
|
|
indexTag32Prefix byte = 7
|
|
indexTagAddrPrefix byte = 8
|
|
)
|
|
|
|
var _ eventstore.Store = (*BadgerBackend)(nil)
|
|
|
|
type BadgerBackend struct {
|
|
Path string
|
|
MaxLimit int
|
|
MaxLimitNegentropy int
|
|
BadgerOptionsModifier func(badger.Options) badger.Options
|
|
|
|
// Experimental
|
|
SkipIndexingTag func(event nostr.Event, tagName string, tagValue string) bool
|
|
// Experimental
|
|
IndexLongerTag func(event nostr.Event, tagName string, tagValue string) bool
|
|
|
|
*badger.DB
|
|
|
|
serial atomic.Uint32
|
|
}
|
|
|
|
func (b *BadgerBackend) Init() error {
|
|
opts := badger.DefaultOptions(b.Path)
|
|
if b.BadgerOptionsModifier != nil {
|
|
opts = b.BadgerOptionsModifier(opts)
|
|
}
|
|
|
|
db, err := badger.Open(opts)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
b.DB = db
|
|
|
|
if err := b.runMigrations(); err != nil {
|
|
return fmt.Errorf("error running migrations: %w", err)
|
|
}
|
|
|
|
if b.MaxLimit != 0 {
|
|
b.MaxLimitNegentropy = b.MaxLimit
|
|
} else {
|
|
b.MaxLimit = 1000
|
|
if b.MaxLimitNegentropy == 0 {
|
|
b.MaxLimitNegentropy = 16777216
|
|
}
|
|
}
|
|
|
|
if err := b.DB.View(func(txn *badger.Txn) error {
|
|
it := txn.NewIterator(badger.IteratorOptions{
|
|
Prefix: []byte{0},
|
|
Reverse: true,
|
|
})
|
|
it.Seek([]byte{1})
|
|
if it.Valid() {
|
|
key := it.Item().Key()
|
|
idx := key[1:]
|
|
serial := binary.BigEndian.Uint32(idx)
|
|
b.serial.Store(serial)
|
|
}
|
|
it.Close()
|
|
return nil
|
|
}); err != nil {
|
|
return fmt.Errorf("error initializing serial: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (b *BadgerBackend) Close() {
|
|
b.DB.Close()
|
|
}
|
|
|
|
func (b *BadgerBackend) Serial() []byte {
|
|
next := b.serial.Add(1)
|
|
vb := make([]byte, 5)
|
|
vb[0] = rawEventStorePrefix
|
|
binary.BigEndian.PutUint32(vb[1:], next)
|
|
return vb
|
|
}
|