Refactor database methods: simplify SaveEvent signature, enhance logging, and introduce deletion check logic with CheckForDeleted.

This commit is contained in:
2025-09-03 20:59:23 +01:00
parent 5cadf9c933
commit b08e94807b
26 changed files with 293 additions and 151 deletions

View File

@@ -3,120 +3,23 @@ package database
import (
"bytes"
"context"
"sort"
"database.orly/indexes"
"database.orly/indexes/types"
"encoders.orly/event"
"encoders.orly/filter"
"encoders.orly/kind"
"encoders.orly/tag"
"encoders.orly/tag/atag"
"github.com/dgraph-io/badger/v4"
"interfaces.orly/store"
"lol.mleku.dev/chk"
"lol.mleku.dev/errorf"
"lol.mleku.dev/log"
)
// SaveEvent saves an event to the database, generating all the necessary indexes.
func (d *D) SaveEvent(
c context.Context, ev *event.E, noVerify bool, owners [][]byte,
) (kc, vc int, err error) {
if !noVerify {
// check if the event already exists
var ser *types.Uint40
if ser, err = d.GetSerialById(ev.ID); err == nil && ser != nil {
err = errorf.E("event already exists: %0x", ev.ID)
return
}
}
// check if an existing delete event references this event submission
if kind.IsParameterizedReplaceable(ev.Kind) {
var idxs []Range
// construct a tag
t := ev.Tags.GetFirst([]byte("d"))
a := atag.T{
Kind: kind.New(ev.Kind),
PubKey: ev.Pubkey,
DTag: t.Value(),
}
at := a.Marshal(nil)
if idxs, err = GetIndexesFromFilter(
&filter.F{
Authors: tag.NewFromBytesSlice(ev.Pubkey),
Kinds: kind.NewS(kind.Deletion),
Tags: tag.NewS(tag.NewFromAny("#a", at)),
},
); chk.E(err) {
return
}
var sers types.Uint40s
for _, idx := range idxs {
var s types.Uint40s
if s, err = d.GetSerialsByRange(idx); chk.E(err) {
return
}
sers = append(sers, s...)
}
if len(sers) > 0 {
// there can be multiple of these because the author/kind/tag is a
// stable value but refers to any event from the author, of the
// kind, with the identifier. so we need to fetch the full ID index
// to get the timestamp and ensure that the event post-dates it.
// otherwise, it should be rejected.
var idPkTss []*store.IdPkTs
var tmp []*store.IdPkTs
if tmp, err = d.GetFullIdPubkeyBySerials(sers); chk.E(err) {
return
}
idPkTss = append(idPkTss, tmp...)
// sort by timestamp, so the first is the newest
sort.Slice(
idPkTss, func(i, j int) bool {
return idPkTss[i].Ts > idPkTss[j].Ts
},
)
if ev.CreatedAt < idPkTss[0].Ts {
err = errorf.E(
"blocked: %0x was deleted by address %s because it is older than the delete: event: %d delete: %d",
ev.ID, at, ev.CreatedAt, idPkTss[0].Ts,
)
return
}
return
}
} else {
var idxs []Range
keys := [][]byte{ev.Pubkey}
for _, owner := range owners {
keys = append(keys, owner)
}
if idxs, err = GetIndexesFromFilter(
&filter.F{
Authors: tag.NewFromBytesSlice(keys...),
Kinds: kind.NewS(kind.Deletion),
Tags: tag.NewS(tag.NewFromAny("#e", ev.ID)),
},
); chk.E(err) {
return
}
var sers types.Uint40s
for _, idx := range idxs {
var s types.Uint40s
if s, err = d.GetSerialsByRange(idx); chk.E(err) {
return
}
sers = append(sers, s...)
}
if len(sers) > 0 {
// really there can only be one of these; the chances of an idhash
// collision are basically zero in practice, at least, one in a
// billion or more anyway, more than a human is going to create.
err = errorf.E("blocked: event %0x deleted by event ID", ev.ID)
return
}
func (d *D) SaveEvent(c context.Context, ev *event.E) (kc, vc int, err error) {
// check if the event already exists
var ser *types.Uint40
if ser, err = d.GetSerialById(ev.ID); err == nil && ser != nil {
err = errorf.E("event already exists: %0x", ev.ID)
return
}
// Get the next sequence number for the event
var serial uint64