From c2c6720e01a7736240391a482f9b1f38c5d1caa4 Mon Sep 17 00:00:00 2001 From: mleku Date: Wed, 10 Sep 2025 20:11:59 +0100 Subject: [PATCH] Enhance `SaveEvent` logic to handle older event rejection with error reporting, validate timestamps in parameterized replaceable events, and improve `HandleEvent` error handling for blocked events. --- app/handle-event.go | 12 +++++++++++- pkg/database/save-event.go | 37 ++++++++++++++++++++++++++++++------- 2 files changed, 41 insertions(+), 8 deletions(-) diff --git a/app/handle-event.go b/app/handle-event.go index 40cef0d..5b4053a 100644 --- a/app/handle-event.go +++ b/app/handle-event.go @@ -129,7 +129,17 @@ func (l *Listener) HandleEvent(msg []byte) (err error) { } // store the event log.I.F("saving event %0x, %s", env.E.ID, env.E.Serialize()) - if _, _, err = l.SaveEvent(l.Ctx, env.E); chk.E(err) { + if _, _, err = l.SaveEvent(l.Ctx, env.E); err != nil { + if strings.HasPrefix(err.Error(), "blocked:") { + errStr := err.Error()[len("blocked: "):len(err.Error())] + if err = Ok.Error( + l, env, errStr, + ); chk.E(err) { + return + } + return + } + chk.E(err) return } // Send a success response storing diff --git a/pkg/database/save-event.go b/pkg/database/save-event.go index 0c789fd..1e58f0c 100644 --- a/pkg/database/save-event.go +++ b/pkg/database/save-event.go @@ -99,12 +99,13 @@ func (d *D) SaveEvent(c context.Context, ev *event.E) (kc, vc int, err error) { } } } else { - // Don't save the older event + // Don't save the older event - return an error + err = errorf.E("blocked: event is older than existing replaceable event") return } } } else if kind.IsParameterizedReplaceable(ev.Kind) { - // find the events and delete them + // find the events and check timestamps before deleting dTag := ev.Tags.GetFirst([]byte("d")) if dTag == nil { err = errorf.E("event is missing a d tag identifier") @@ -121,19 +122,41 @@ func (d *D) SaveEvent(c context.Context, ev *event.E) (kc, vc int, err error) { if sers, err = d.GetSerialsFromFilter(f); chk.E(err) { return } - // if found, delete them + // if found, check timestamps before deleting if len(sers) > 0 { + var shouldReplace bool = true for _, s := range sers { var oldEv *event.E if oldEv, err = d.FetchEventBySerial(s); chk.E(err) { continue } - if err = d.DeleteEventBySerial( - c, s, oldEv, - ); chk.E(err) { - continue + // Only replace if the new event is newer or same timestamp + if ev.CreatedAt < oldEv.CreatedAt { + log.I.F("SaveEvent: rejecting older addressable event ID=%s (created_at=%d) - existing event ID=%s (created_at=%d)", + hex.Enc(ev.ID), ev.CreatedAt, hex.Enc(oldEv.ID), oldEv.CreatedAt) + shouldReplace = false + break } } + if shouldReplace { + for _, s := range sers { + var oldEv *event.E + if oldEv, err = d.FetchEventBySerial(s); chk.E(err) { + continue + } + log.I.F("SaveEvent: replacing older addressable event ID=%s (created_at=%d) with newer event ID=%s (created_at=%d)", + hex.Enc(oldEv.ID), oldEv.CreatedAt, hex.Enc(ev.ID), ev.CreatedAt) + if err = d.DeleteEventBySerial( + c, s, oldEv, + ); chk.E(err) { + continue + } + } + } else { + // Don't save the older event - return an error + err = errorf.E("blocked: event is older than existing addressable event") + return + } } } // Get the next sequence number for the event