From 4d1774264affd097dceaa0b1719c0a53e78bc344 Mon Sep 17 00:00:00 2001 From: fiatjaf Date: Sun, 12 Oct 2025 13:55:44 +0000 Subject: [PATCH] mmm: add debug helpers for fixing an inconsistent db. --- eventstore/mmm/debug.go | 89 +++++++++++++++++++++++++++++++++++++++++ eventstore/mmm/query.go | 2 +- 2 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 eventstore/mmm/debug.go diff --git a/eventstore/mmm/debug.go b/eventstore/mmm/debug.go new file mode 100644 index 0000000..b671443 --- /dev/null +++ b/eventstore/mmm/debug.go @@ -0,0 +1,89 @@ +package mmm + +import ( + "encoding/binary" + + "fiatjaf.com/nostr" + "github.com/PowerDNS/lmdb-go/lmdb" +) + +func (b *MultiMmapManager) DebugAtPosition(offset uint64) (idPrefix []byte, layers []*IndexingLayer) { + b.lmdbEnv.View(func(txn *lmdb.Txn) error { + txn.RawRead = true + + cursor, err := txn.OpenCursor(b.indexId) + if err != nil { + panic(err) + } + defer cursor.Close() + + for key, val, err := cursor.Get(nil, nil, lmdb.First); err == nil; key, val, err = cursor.Get(key, val, lmdb.Next) { + pos := positionFromBytes(val[0:12]) + + if pos.start == offset { + idPrefix = key + layers = make([]*IndexingLayer, 0, (len(val)-12)/2) + + for s := 12; s < len(val); s += 2 { + layer := b.layers.ByID(binary.BigEndian.Uint16(val[s : s+2])) + layers = append(layers, layer) + } + + return nil + } + } + + return nil + }) + + return +} + +func (il *IndexingLayer) HasAtPosition(offset uint64) ( + exists bool, + createdAt nostr.Timestamp, + kind nostr.Kind, +) { + il.lmdbEnv.View(func(txn *lmdb.Txn) error { + txn.RawRead = true + + { + cursor, err := txn.OpenCursor(il.indexCreatedAt) + if err != nil { + panic(err) + } + defer cursor.Close() + + for key, val, err := cursor.Get(nil, nil, lmdb.First); err == nil; key, val, err = cursor.Get(key, val, lmdb.Next) { + pos := positionFromBytes(val[0:12]) + + if pos.start == offset { + exists = true + createdAt = nostr.Timestamp(binary.BigEndian.Uint32(key)) + break + } + } + } + + { + cursor, err := txn.OpenCursor(il.indexKind) + if err != nil { + panic(err) + } + defer cursor.Close() + + for key, val, err := cursor.Get(nil, nil, lmdb.First); err == nil; key, val, err = cursor.Get(key, val, lmdb.Next) { + pos := positionFromBytes(val[0:12]) + if pos.start == offset { + exists = true + kind = nostr.Kind(binary.BigEndian.Uint16(key)) + break + } + } + } + + return nil + }) + + return +} diff --git a/eventstore/mmm/query.go b/eventstore/mmm/query.go index 899c51e..ae40d34 100644 --- a/eventstore/mmm/query.go +++ b/eventstore/mmm/query.go @@ -49,7 +49,7 @@ func (b *MultiMmapManager) queryByIDs( pos := positionFromBytes(val[0:12]) evt := nostr.Event{} if err := b.loadEvent(pos, &evt); err != nil { - panic(fmt.Errorf("failed to decode event from %v: %w", pos, err)) + panic(fmt.Errorf("failed to decode event %s from %v: %w", id, pos, err)) } restrictionSatisfied := restrictToLayer == nil