diff --git a/khatru/deleting.go b/khatru/deleting.go index 69c2d51..0502ada 100644 --- a/khatru/deleting.go +++ b/khatru/deleting.go @@ -78,6 +78,9 @@ func (rl *Relay) handleDeleteRequest(ctx context.Context, evt nostr.Event) error } haveDeletedSomething = true + if rl.OnEventDeleted != nil { + rl.OnEventDeleted(ctx, target) + } return nil }) } else { diff --git a/khatru/expiration.go b/khatru/expiration.go index 997e259..2f6e8f0 100644 --- a/khatru/expiration.go +++ b/khatru/expiration.go @@ -39,9 +39,15 @@ type expirationManager struct { events expiringEventHeap mu sync.Mutex + // a function to query the relay database, generally the same as relay.queryStored queryStored func(ctx context.Context, filter nostr.Filter) iter.Seq[nostr.Event] + + // a function to delete an event from the relay database, generally the same as relay.DeleteEvent deleteEvent func(ctx context.Context, id nostr.ID) error + // a function to call after an event has been deleted, generally the same as relay.OnEventDeleted + deleteCallback func(ctx context.Context, id nostr.Event) + interval time.Duration initialScanDone bool kill chan struct{} // used for manually killing this @@ -109,7 +115,11 @@ func (em *expirationManager) checkExpiredEvents(ctx context.Context) { heap.Pop(&em.events) ctx := context.WithValue(ctx, internalCallKey, struct{}{}) - em.deleteEvent(ctx, next.id) + if nil == em.deleteEvent(ctx, next.id) && em.deleteCallback != nil { + for evt := range em.queryStored(ctx, nostr.Filter{IDs: []nostr.ID{next.id}}) { + em.deleteCallback(ctx, evt) + } + } } } @@ -142,12 +152,14 @@ func (em *expirationManager) removeEvent(id nostr.ID) { func (rl *Relay) StartExpirationManager( queryStored func(ctx context.Context, filter nostr.Filter) iter.Seq[nostr.Event], deleteEvent func(ctx context.Context, id nostr.ID) error, + onDeleteCallback func(ctx context.Context, evt nostr.Event), ) { rl.expirationManager = &expirationManager{ events: make(expiringEventHeap, 0), - queryStored: queryStored, - deleteEvent: deleteEvent, + queryStored: queryStored, + deleteEvent: deleteEvent, + deleteCallback: onDeleteCallback, interval: time.Hour, kill: make(chan struct{}), diff --git a/khatru/relay.go b/khatru/relay.go index 4355072..f395501 100644 --- a/khatru/relay.go +++ b/khatru/relay.go @@ -69,6 +69,7 @@ type Relay struct { ReplaceEvent func(ctx context.Context, event nostr.Event) error DeleteEvent func(ctx context.Context, id nostr.ID) error OnEventSaved func(ctx context.Context, event nostr.Event) + OnEventDeleted func(ctx context.Context, deleted nostr.Event) OnEphemeralEvent func(ctx context.Context, event nostr.Event) OnRequest func(ctx context.Context, filter nostr.Filter) (reject bool, msg string) OnCount func(ctx context.Context, filter nostr.Filter) (reject bool, msg string) @@ -155,7 +156,15 @@ func (rl *Relay) UseEventstore(store eventstore.Store, maxQueryLimit int) { } // only when using the eventstore we automatically set up the expiration manager - rl.StartExpirationManager(rl.QueryStored, rl.DeleteEvent) + rl.StartExpirationManager(func(ctx context.Context, filter nostr.Filter) iter.Seq[nostr.Event] { + return rl.QueryStored(ctx, filter) + }, func(ctx context.Context, id nostr.ID) error { + return rl.DeleteEvent(ctx, id) + }, func(ctx context.Context, evt nostr.Event) { + if rl.OnEventDeleted != nil { + rl.OnEventDeleted(ctx, evt) + } + }) } func (rl *Relay) getBaseURL(r *http.Request) string {