diff --git a/nip47/event_handler.go b/nip47/event_handler.go index c765d74da..d8e1b7b35 100644 --- a/nip47/event_handler.go +++ b/nip47/event_handler.go @@ -23,6 +23,10 @@ import ( "gorm.io/gorm" ) +const ( + MaxRequestEventsPerApp = 1000 +) + func (svc *nip47Service) HandleEvent(ctx context.Context, pool nostrmodels.SimplePool, event *nostr.Event, lnClient lnclient.LNClient) { var nip47Response *models.Response logger.Logger.WithFields(logrus.Fields{ @@ -171,6 +175,9 @@ func (svc *nip47Service) HandleEvent(ctx context.Context, pool nostrmodels.Simpl Model(&requestEvent). Update("app_id", app.ID). Error + if err == nil { + go svc.pruneRequestEvents(app.ID) + } if err != nil { logger.Logger.WithFields(logrus.Fields{ "appPubkey": event.PubKey, @@ -556,3 +563,21 @@ func (svc *nip47Service) publishResponseEvent(ctx context.Context, pool nostrmod return nil } + +func (svc *nip47Service) pruneRequestEvents(appId uint) { + err := svc.db.Exec(` + DELETE FROM request_events + WHERE app_id = ? AND id NOT IN ( + SELECT id FROM request_events + WHERE app_id = ? + ORDER BY id DESC + LIMIT ? + ) + `, appId, appId, MaxRequestEventsPerApp).Error + + if err != nil { + logger.Logger.WithFields(logrus.Fields{ + "appId": appId, + }).WithError(err).Error("Failed to prune request events") + } +} diff --git a/nip47/prune_test.go b/nip47/prune_test.go new file mode 100644 index 000000000..e389e598d --- /dev/null +++ b/nip47/prune_test.go @@ -0,0 +1,55 @@ +package nip47 + +import ( + "fmt" + "testing" + "time" + + "github.com/getAlby/hub/db" + "github.com/getAlby/hub/tests" + "github.com/stretchr/testify/assert" +) + +func TestPruneRequestEvents(t *testing.T) { + svc, err := tests.CreateTestService(t) + assert.NoError(t, err) + defer svc.Remove() + + app := db.App{ + Name: "Test App", + AppPubkey: "pubkey", + } + err = svc.DB.Create(&app).Error + assert.NoError(t, err) + + nip47Svc := &nip47Service{ + db: svc.DB, + } + + for i := 0; i < 1005; i++ { + requestEvent := db.RequestEvent{ + AppId: &app.ID, + NostrId: fmt.Sprintf("event_%d", i), + State: db.REQUEST_EVENT_STATE_HANDLER_EXECUTED, + CreatedAt: time.Now(), + } + err = svc.DB.Create(&requestEvent).Error + assert.NoError(t, err) + } + + var count int64 + svc.DB.Model(&db.RequestEvent{}).Where("app_id = ?", app.ID).Count(&count) + assert.Equal(t, int64(1005), count) + + nip47Svc.pruneRequestEvents(app.ID) + + svc.DB.Model(&db.RequestEvent{}).Where("app_id = ?", app.ID).Count(&count) + assert.Equal(t, int64(MaxRequestEventsPerApp), count) + + + var remaining []db.RequestEvent + svc.DB.Where("app_id = ?", app.ID).Order("id asc").Find(&remaining) + assert.Equal(t, MaxRequestEventsPerApp, len(remaining)) + assert.Equal(t, "event_5", remaining[0].NostrId) + assert.Equal(t, "event_1004", remaining[len(remaining)-1].NostrId) +}