You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

134 lines
3.0 KiB

//go:build !(js && wasm)
package bbolt
import (
"bytes"
"context"
"errors"
bolt "go.etcd.io/bbolt"
"lol.mleku.dev/chk"
"next.orly.dev/pkg/database"
"next.orly.dev/pkg/database/indexes/types"
"git.mleku.dev/mleku/nostr/encoders/event"
"git.mleku.dev/mleku/nostr/encoders/filter"
)
// FetchEventBySerial fetches an event by its serial number.
func (b *B) FetchEventBySerial(ser *types.Uint40) (ev *event.E, err error) {
if ser == nil {
return nil, errors.New("bbolt: nil serial")
}
serial := ser.Get()
key := makeSerialKey(serial)
err = b.db.View(func(tx *bolt.Tx) error {
// Get event ID first
seiBucket := tx.Bucket(bucketSei)
var eventId []byte
if seiBucket != nil {
eventId = seiBucket.Get(key)
}
// Try compact event storage first
cmpBucket := tx.Bucket(bucketCmp)
if cmpBucket != nil {
data := cmpBucket.Get(key)
if data != nil && eventId != nil && len(eventId) == 32 {
// Unmarshal compact event
resolver := &bboltSerialResolver{b: b}
ev, err = database.UnmarshalCompactEvent(data, eventId, resolver)
if err == nil {
return nil
}
// Fall through to try legacy format
}
}
// Try legacy event storage
evtBucket := tx.Bucket(bucketEvt)
if evtBucket != nil {
data := evtBucket.Get(key)
if data != nil {
ev = new(event.E)
reader := bytes.NewReader(data)
if err = ev.UnmarshalBinary(reader); err == nil {
return nil
}
}
}
return errors.New("bbolt: event not found")
})
return
}
// FetchEventsBySerials fetches multiple events by their serial numbers.
func (b *B) FetchEventsBySerials(serials []*types.Uint40) (events map[uint64]*event.E, err error) {
events = make(map[uint64]*event.E, len(serials))
err = b.db.View(func(tx *bolt.Tx) error {
cmpBucket := tx.Bucket(bucketCmp)
evtBucket := tx.Bucket(bucketEvt)
seiBucket := tx.Bucket(bucketSei)
resolver := &bboltSerialResolver{b: b}
for _, ser := range serials {
if ser == nil {
continue
}
serial := ser.Get()
key := makeSerialKey(serial)
// Get event ID
var eventId []byte
if seiBucket != nil {
eventId = seiBucket.Get(key)
}
// Try compact event storage first
if cmpBucket != nil {
data := cmpBucket.Get(key)
if data != nil && eventId != nil && len(eventId) == 32 {
ev, e := database.UnmarshalCompactEvent(data, eventId, resolver)
if e == nil {
events[serial] = ev
continue
}
}
}
// Try legacy event storage
if evtBucket != nil {
data := evtBucket.Get(key)
if data != nil {
ev := new(event.E)
reader := bytes.NewReader(data)
if e := ev.UnmarshalBinary(reader); e == nil {
events[serial] = ev
}
}
}
}
return nil
})
return
}
// CountEvents counts events matching a filter.
func (b *B) CountEvents(c context.Context, f *filter.F) (count int, approximate bool, err error) {
// Get serials matching filter
var serials types.Uint40s
if serials, err = b.GetSerialsFromFilter(f); chk.E(err) {
return
}
count = len(serials)
approximate = false
return
}