diff --git a/nip47/nip47_service.go b/nip47/nip47_service.go index 25c0b467..50d70d30 100644 --- a/nip47/nip47_service.go +++ b/nip47/nip47_service.go @@ -2,6 +2,7 @@ package nip47 import ( "context" + "errors" "time" "github.com/getAlby/go-nostr" @@ -114,6 +115,18 @@ func (svc *nip47Service) StartNip47InfoPublisher(ctx context.Context, pool *nost case req := <-svc.nip47InfoPublishQueue.Channel(): _, err := svc.PublishNip47Info(ctx, pool, req.AppId, req.AppWalletPubKey, req.AppWalletPrivKey, req.RelayUrl, lnClient) if err != nil { + // the app connection no longer exists (e.g. it was deleted), + // so the info event can never be published - drop the item + // instead of retrying forever + if errors.Is(err, gorm.ErrRecordNotFound) { + logger.Logger.WithError(err).WithFields(logrus.Fields{ + "app_id": req.AppId, + "wallet_pubkey": req.AppWalletPubKey, + "relay_url": req.RelayUrl, + }).Warn("Skipping NIP47 info publish for deleted app") + continue + } + logger.Logger.WithError(err).WithFields(logrus.Fields{ "wallet_pubkey": req.AppWalletPubKey, "relay_url": req.RelayUrl, diff --git a/nip47/publish_nip47_info_test.go b/nip47/publish_nip47_info_test.go new file mode 100644 index 00000000..548ddc7f --- /dev/null +++ b/nip47/publish_nip47_info_test.go @@ -0,0 +1,36 @@ +package nip47 + +import ( + "context" + "testing" + + "github.com/getAlby/go-nostr" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "gorm.io/gorm" + + "github.com/getAlby/hub/alby" + "github.com/getAlby/hub/tests" +) + +// When an app connection has been deleted, publishing its NIP47 info must +// surface gorm.ErrRecordNotFound so the publish queue can drop the item +// instead of retrying forever. +func TestPublishNip47Info_AppNotFound(t *testing.T) { + svc, err := tests.CreateTestService(t) + require.NoError(t, err) + defer svc.Remove() + + albyOAuthSvc := alby.NewAlbyOAuthService(svc.DB, svc.Cfg, svc.Keys, svc.EventPublisher) + nip47svc := NewNip47Service(svc.DB, svc.Cfg, svc.Keys, svc.EventPublisher, albyOAuthSvc) + + walletPrivKey := nostr.GeneratePrivateKey() + walletPubKey, err := nostr.GetPublicKey(walletPrivKey) + require.NoError(t, err) + + // app id 9999999 does not exist; the DB lookup fails before the relay pool + // is ever used, so a nil pool/lnClient is fine here. + _, err = nip47svc.PublishNip47Info(context.Background(), nil, 9999999, walletPubKey, walletPrivKey, "wss://relay.example.com", nil) + require.Error(t, err) + assert.ErrorIs(t, err, gorm.ErrRecordNotFound) +}