package boltdb import ( "time" "fiatjaf.com/nostr" "fiatjaf.com/nostr/eventstore" "go.etcd.io/bbolt" ) var ( settingsStore = []byte("settingsStore") rawEventStore = []byte("rawEventStore") indexCreatedAt = []byte("indexCreatedAt") indexKind = []byte("indexKind") indexPubkey = []byte("indexPubkey") indexPubkeyKind = []byte("indexPubkeyKind") indexTag = []byte("indexTag") indexTag32 = []byte("indexTag32") indexTagAddr = []byte("indexTagAddr") hllCache = []byte("hllCache") ) var _ eventstore.Store = (*BoltBackend)(nil) type BoltBackend struct { Path string MapSize int64 DB *bbolt.DB EnableHLLCacheFor func(kind nostr.Kind) (useCache bool, skipSavingActualEvent bool) } func (b *BoltBackend) Init() error { db, err := bbolt.Open(b.Path, 0600, &bbolt.Options{ Timeout: 2 * time.Second, PreLoadFreelist: true, FreelistType: bbolt.FreelistMapType, }) if err != nil { return err } db.AllocSize = 64 * 1024 * 1024 db.MaxBatchDelay = time.Millisecond * 40 b.DB = db db.Update(func(txn *bbolt.Tx) error { if _, err := txn.CreateBucketIfNotExists(settingsStore); err != nil { return err } if _, err := txn.CreateBucketIfNotExists(rawEventStore); err != nil { return err } if _, err := txn.CreateBucketIfNotExists(indexCreatedAt); err != nil { return err } if _, err := txn.CreateBucketIfNotExists(indexKind); err != nil { return err } if _, err := txn.CreateBucketIfNotExists(indexPubkey); err != nil { return err } if _, err := txn.CreateBucketIfNotExists(indexPubkeyKind); err != nil { return err } if _, err := txn.CreateBucketIfNotExists(indexTag); err != nil { return err } if _, err := txn.CreateBucketIfNotExists(indexTag32); err != nil { return err } if _, err := txn.CreateBucketIfNotExists(indexTagAddr); err != nil { return err } if _, err := txn.CreateBucketIfNotExists(hllCache); err != nil { return err } return nil }) return b.migrate() } func (b *BoltBackend) Close() { b.DB.Close() }