From 51f4ba9f5ab09c7de75e7776520ceeb352d8f107 Mon Sep 17 00:00:00 2001 From: im-adithya Date: Mon, 15 Jul 2024 20:04:14 +0530 Subject: [PATCH 1/6] feat: add response received column --- internal/nostr/models.go | 15 +++++---- internal/nostr/nostr.go | 4 +++ ...20_add_response_state_to_request_events.go | 33 +++++++++++++++++++ migrations/migrate.go | 1 + 4 files changed, 46 insertions(+), 7 deletions(-) create mode 100644 migrations/202407131920_add_response_state_to_request_events.go diff --git a/internal/nostr/models.go b/internal/nostr/models.go index 76e4a16..98b2d3c 100644 --- a/internal/nostr/models.go +++ b/internal/nostr/models.go @@ -130,13 +130,14 @@ type OnReceiveEOSFunc func(ctx context.Context, subscription *Subscription) type HandleEventFunc func(event *nostr.Event, subscription *Subscription) type RequestEvent struct { - ID uint - SubscriptionId *uint - NostrId string `validate:"required"` - Content string - State string - CreatedAt time.Time - UpdatedAt time.Time + ID uint + SubscriptionId *uint + NostrId string `validate:"required"` + Content string + State string + ResponseReceived bool + CreatedAt time.Time + UpdatedAt time.Time } type ResponseEvent struct { diff --git a/internal/nostr/nostr.go b/internal/nostr/nostr.go index 2332dcd..db1c31c 100644 --- a/internal/nostr/nostr.go +++ b/internal/nostr/nostr.go @@ -794,6 +794,10 @@ func (svc *Service) handleResponseEvent(event *nostr.Event, subscription *Subscr "request_event_id": subscription.RequestEvent.ID, "wallet_pubkey": svc.getWalletPubkey(subscription.Authors), }).Info("Received response event") + if (subscription.RequestEvent != nil) { + subscription.RequestEventDB.ResponseReceived = true + svc.db.Save(&subscription.RequestEventDB) + } responseEvent := ResponseEvent{ NostrId: event.ID, Content: event.Content, diff --git a/migrations/202407131920_add_response_state_to_request_events.go b/migrations/202407131920_add_response_state_to_request_events.go new file mode 100644 index 0000000..721cd88 --- /dev/null +++ b/migrations/202407131920_add_response_state_to_request_events.go @@ -0,0 +1,33 @@ +package migrations + +import ( + "github.com/go-gormigrate/gormigrate/v2" + "gorm.io/gorm" +) + +// Add response_received column to request_events table +var _202407131920_add_response_state_to_request_events = &gormigrate.Migration{ + ID: "202407131920_add_response_state_to_request_events", + Migrate: func(tx *gorm.DB) error { + if err := tx.Exec("ALTER TABLE request_events ADD COLUMN response_received BOOLEAN DEFAULT FALSE").Error; err != nil { + return err + } + + // Update response_received to TRUE if there is a corresponding row in response_events + if err := tx.Exec(` + UPDATE request_events + SET response_received = TRUE + WHERE id IN (SELECT request_id FROM response_events WHERE request_id IS NOT NULL) + `).Error; err != nil { + return err + } + + return nil + }, + Rollback: func(tx *gorm.DB) error { + if err := tx.Exec("ALTER TABLE request_events DROP COLUMN response_received").Error; err != nil { + return err + } + return nil + }, +} diff --git a/migrations/migrate.go b/migrations/migrate.go index b11ab4f..e0280a5 100644 --- a/migrations/migrate.go +++ b/migrations/migrate.go @@ -11,6 +11,7 @@ func Migrate(db *gorm.DB) error { _202402161653_initial_migration, _202404021628_add_uuid_to_subscriptions, _202404031539_add_indexes, + _202407131920_add_response_state_to_request_events, }) return m.Migrate() From d3c7daa0a5bb3655c758dc9bd97dbefb8dfc44fd Mon Sep 17 00:00:00 2001 From: im-adithya Date: Wed, 17 Jul 2024 14:17:51 +0530 Subject: [PATCH 2/6] feat: add response_received_at --- internal/nostr/models.go | 16 ++++----- internal/nostr/nostr.go | 2 +- ...20_add_response_state_to_request_events.go | 33 ------------------- ...20_add_response_state_to_request_events.go | 33 +++++++++++++++++++ migrations/migrate.go | 2 +- 5 files changed, 43 insertions(+), 43 deletions(-) delete mode 100644 migrations/202407131920_add_response_state_to_request_events.go create mode 100644 migrations/202407171220_add_response_state_to_request_events.go diff --git a/internal/nostr/models.go b/internal/nostr/models.go index 98b2d3c..5a5ed88 100644 --- a/internal/nostr/models.go +++ b/internal/nostr/models.go @@ -130,14 +130,14 @@ type OnReceiveEOSFunc func(ctx context.Context, subscription *Subscription) type HandleEventFunc func(event *nostr.Event, subscription *Subscription) type RequestEvent struct { - ID uint - SubscriptionId *uint - NostrId string `validate:"required"` - Content string - State string - ResponseReceived bool - CreatedAt time.Time - UpdatedAt time.Time + ID uint + SubscriptionId *uint + NostrId string `validate:"required"` + Content string + State string + ResponseReceivedAt time.Time + CreatedAt time.Time + UpdatedAt time.Time } type ResponseEvent struct { diff --git a/internal/nostr/nostr.go b/internal/nostr/nostr.go index db1c31c..caa42dc 100644 --- a/internal/nostr/nostr.go +++ b/internal/nostr/nostr.go @@ -795,7 +795,7 @@ func (svc *Service) handleResponseEvent(event *nostr.Event, subscription *Subscr "wallet_pubkey": svc.getWalletPubkey(subscription.Authors), }).Info("Received response event") if (subscription.RequestEvent != nil) { - subscription.RequestEventDB.ResponseReceived = true + subscription.RequestEventDB.ResponseReceivedAt = time.Now() svc.db.Save(&subscription.RequestEventDB) } responseEvent := ResponseEvent{ diff --git a/migrations/202407131920_add_response_state_to_request_events.go b/migrations/202407131920_add_response_state_to_request_events.go deleted file mode 100644 index 721cd88..0000000 --- a/migrations/202407131920_add_response_state_to_request_events.go +++ /dev/null @@ -1,33 +0,0 @@ -package migrations - -import ( - "github.com/go-gormigrate/gormigrate/v2" - "gorm.io/gorm" -) - -// Add response_received column to request_events table -var _202407131920_add_response_state_to_request_events = &gormigrate.Migration{ - ID: "202407131920_add_response_state_to_request_events", - Migrate: func(tx *gorm.DB) error { - if err := tx.Exec("ALTER TABLE request_events ADD COLUMN response_received BOOLEAN DEFAULT FALSE").Error; err != nil { - return err - } - - // Update response_received to TRUE if there is a corresponding row in response_events - if err := tx.Exec(` - UPDATE request_events - SET response_received = TRUE - WHERE id IN (SELECT request_id FROM response_events WHERE request_id IS NOT NULL) - `).Error; err != nil { - return err - } - - return nil - }, - Rollback: func(tx *gorm.DB) error { - if err := tx.Exec("ALTER TABLE request_events DROP COLUMN response_received").Error; err != nil { - return err - } - return nil - }, -} diff --git a/migrations/202407171220_add_response_state_to_request_events.go b/migrations/202407171220_add_response_state_to_request_events.go new file mode 100644 index 0000000..9c904a6 --- /dev/null +++ b/migrations/202407171220_add_response_state_to_request_events.go @@ -0,0 +1,33 @@ +package migrations + +import ( + "github.com/go-gormigrate/gormigrate/v2" + "gorm.io/gorm" +) + +// Add response_received_at column to request_events table +var _202407171220_add_response_received_at_to_request_events = &gormigrate.Migration{ + ID: "202407171220_add_response_received_at_to_request_events", + Migrate: func(tx *gorm.DB) error { + if err := tx.Exec("ALTER TABLE request_events ADD COLUMN response_received_at TIMESTAMP DEFAULT '0001-01-01 00:00:00+00'").Error; err != nil { + return err + } + + // Update response_received_at if there is a corresponding row in response_events + if err := tx.Exec(` + UPDATE request_events re + SET response_received_at = (SELECT created_at FROM response_events WHERE request_id = re.id) + WHERE id IN (SELECT request_id FROM response_events WHERE request_id IS NOT NULL) + `).Error; err != nil { + return err + } + + return nil + }, + Rollback: func(tx *gorm.DB) error { + if err := tx.Exec("ALTER TABLE request_events DROP COLUMN response_received_at").Error; err != nil { + return err + } + return nil + }, +} diff --git a/migrations/migrate.go b/migrations/migrate.go index e0280a5..444adee 100644 --- a/migrations/migrate.go +++ b/migrations/migrate.go @@ -11,7 +11,7 @@ func Migrate(db *gorm.DB) error { _202402161653_initial_migration, _202404021628_add_uuid_to_subscriptions, _202404031539_add_indexes, - _202407131920_add_response_state_to_request_events, + _202407171220_add_response_received_at_to_request_events, }) return m.Migrate() From 3f15f1e8c7c6b8152e4f0677f02f0ce5d62b927d Mon Sep 17 00:00:00 2001 From: im-adithya Date: Wed, 17 Jul 2024 14:46:07 +0530 Subject: [PATCH 3/6] chore: change migration file name --- ...=> 202407171220_add_response_received_at_to_request_events.go} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename migrations/{202407171220_add_response_state_to_request_events.go => 202407171220_add_response_received_at_to_request_events.go} (100%) diff --git a/migrations/202407171220_add_response_state_to_request_events.go b/migrations/202407171220_add_response_received_at_to_request_events.go similarity index 100% rename from migrations/202407171220_add_response_state_to_request_events.go rename to migrations/202407171220_add_response_received_at_to_request_events.go From af907755116746fcc74b69796497edf8636bd43c Mon Sep 17 00:00:00 2001 From: im-adithya Date: Wed, 17 Jul 2024 14:52:34 +0530 Subject: [PATCH 4/6] chore: use null instead of default --- .../202407171220_add_response_received_at_to_request_events.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/migrations/202407171220_add_response_received_at_to_request_events.go b/migrations/202407171220_add_response_received_at_to_request_events.go index 9c904a6..2897223 100644 --- a/migrations/202407171220_add_response_received_at_to_request_events.go +++ b/migrations/202407171220_add_response_received_at_to_request_events.go @@ -9,7 +9,7 @@ import ( var _202407171220_add_response_received_at_to_request_events = &gormigrate.Migration{ ID: "202407171220_add_response_received_at_to_request_events", Migrate: func(tx *gorm.DB) error { - if err := tx.Exec("ALTER TABLE request_events ADD COLUMN response_received_at TIMESTAMP DEFAULT '0001-01-01 00:00:00+00'").Error; err != nil { + if err := tx.Exec("ALTER TABLE request_events ADD COLUMN response_received_at TIMESTAMP NULL").Error; err != nil { return err } From 1c7205fc6ee84d4092a38ee42bd52577f2d04118 Mon Sep 17 00:00:00 2001 From: im-adithya Date: Wed, 17 Jul 2024 17:14:32 +0530 Subject: [PATCH 5/6] chore: set response_received_at to created_at in migration --- ...202407171220_add_response_received_at_to_request_events.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/migrations/202407171220_add_response_received_at_to_request_events.go b/migrations/202407171220_add_response_received_at_to_request_events.go index 2897223..514e504 100644 --- a/migrations/202407171220_add_response_received_at_to_request_events.go +++ b/migrations/202407171220_add_response_received_at_to_request_events.go @@ -15,9 +15,7 @@ var _202407171220_add_response_received_at_to_request_events = &gormigrate.Migra // Update response_received_at if there is a corresponding row in response_events if err := tx.Exec(` - UPDATE request_events re - SET response_received_at = (SELECT created_at FROM response_events WHERE request_id = re.id) - WHERE id IN (SELECT request_id FROM response_events WHERE request_id IS NOT NULL) + UPDATE request_events SET response_received_at = created_at `).Error; err != nil { return err } From bc18b452d3587b2d9de90726911028a4bd1cfcb5 Mon Sep 17 00:00:00 2001 From: im-adithya Date: Wed, 31 Jul 2024 13:22:20 +0530 Subject: [PATCH 6/6] chore: remove RequestEventDB from subscriptions --- internal/nostr/models.go | 6 ++--- internal/nostr/nostr.go | 51 +++++++++++++++++++--------------------- 2 files changed, 27 insertions(+), 30 deletions(-) diff --git a/internal/nostr/models.go b/internal/nostr/models.go index 5a5ed88..89e1f28 100644 --- a/internal/nostr/models.go +++ b/internal/nostr/models.go @@ -41,8 +41,7 @@ type Subscription struct { UpdatedAt time.Time Uuid string `gorm:"type:uuid;default:gen_random_uuid()"` EventChan chan *nostr.Event `gorm:"-"` - RequestEvent *nostr.Event `gorm:"-"` - RequestEventDB RequestEvent `gorm:"-"` + RequestEvent *RequestEvent `gorm:"-"` // TODO: fix an elegant solution to store datatypes IdsString string @@ -132,12 +131,13 @@ type HandleEventFunc func(event *nostr.Event, subscription *Subscription) type RequestEvent struct { ID uint SubscriptionId *uint - NostrId string `validate:"required"` + NostrId string `validate:"required"` Content string State string ResponseReceivedAt time.Time CreatedAt time.Time UpdatedAt time.Time + SignedEvent *nostr.Event `gorm:"-"` } type ResponseEvent struct { diff --git a/internal/nostr/nostr.go b/internal/nostr/nostr.go index 899a8f2..8962d21 100644 --- a/internal/nostr/nostr.go +++ b/internal/nostr/nostr.go @@ -331,8 +331,9 @@ func (svc *Service) NIP47Handler(c echo.Context) error { } requestEvent := RequestEvent{ - NostrId: requestData.SignedEvent.ID, - Content: requestData.SignedEvent.Content, + NostrId: requestData.SignedEvent.ID, + Content: requestData.SignedEvent.Content, + SignedEvent: requestData.SignedEvent, } if err := svc.db.Create(&requestEvent).Error; err != nil { @@ -348,11 +349,7 @@ func (svc *Service) NIP47Handler(c echo.Context) error { }) } - subscription := svc.prepareNIP47Subscription(NIP47WebhookRequest{ - RelayUrl: requestData.RelayUrl, - WalletPubkey: requestData.WalletPubkey, - SignedEvent: requestData.SignedEvent, - }, requestEvent) + subscription := svc.prepareNIP47Subscription(requestData.RelayUrl, requestData.WalletPubkey, "", requestEvent) ctx, cancel := context.WithTimeout(c.Request().Context(), 90*time.Second) defer cancel() @@ -434,8 +431,9 @@ func (svc *Service) NIP47WebhookHandler(c echo.Context) error { } requestEvent := RequestEvent{ - NostrId: requestData.SignedEvent.ID, - Content: requestData.SignedEvent.Content, + NostrId: requestData.SignedEvent.ID, + Content: requestData.SignedEvent.Content, + SignedEvent: requestData.SignedEvent, } if err := svc.db.Create(&requestEvent).Error; err != nil { @@ -451,7 +449,7 @@ func (svc *Service) NIP47WebhookHandler(c echo.Context) error { }) } - subscription := svc.prepareNIP47Subscription(requestData, requestEvent) + subscription := svc.prepareNIP47Subscription(requestData.RelayUrl, requestData.WalletPubkey, requestData.WebhookUrl, requestEvent) ctx, cancel := context.WithTimeout(svc.Ctx, 90*time.Second) defer cancel() @@ -462,18 +460,17 @@ func (svc *Service) NIP47WebhookHandler(c echo.Context) error { }) } -func (svc *Service) prepareNIP47Subscription(requestData NIP47WebhookRequest, requestEvent RequestEvent) (Subscription) { +func (svc *Service) prepareNIP47Subscription(relayUrl, walletPubkey, webhookUrl string, requestEvent RequestEvent) (Subscription) { return Subscription{ - RelayUrl: requestData.RelayUrl, - WebhookUrl: requestData.WebhookUrl, + RelayUrl: relayUrl, + WebhookUrl: webhookUrl, Open: true, - Authors: &[]string{requestData.WalletPubkey}, + Authors: &[]string{walletPubkey}, Kinds: &[]int{NIP_47_RESPONSE_KIND}, - Tags: &nostr.TagMap{"e": []string{requestData.SignedEvent.ID}}, + Tags: &nostr.TagMap{"e": []string{requestEvent.NostrId}}, Since: time.Now(), Limit: 1, - RequestEvent: requestData.SignedEvent, - RequestEventDB: requestEvent, + RequestEvent: &requestEvent, EventChan: make(chan *nostr.Event, 1), Uuid: uuid.New().String(), } @@ -742,10 +739,10 @@ func (svc *Service) startSubscription(ctx context.Context, subscription *Subscri // Save the request event state and stop the // subscription if it's an NIP47 request if (subscription.RequestEvent != nil) { - if (subscription.RequestEventDB.State == "") { - subscription.RequestEventDB.State = REQUEST_EVENT_PUBLISH_FAILED + if (subscription.RequestEvent.State == "") { + subscription.RequestEvent.State = REQUEST_EVENT_PUBLISH_FAILED } - svc.db.Save(&subscription.RequestEventDB) + svc.db.Save(&subscription.RequestEvent) // stop the subscription as it is one time svc.stopSubscription(subscription) } @@ -764,7 +761,7 @@ func (svc *Service) publishRequestEvent(ctx context.Context, subscription *Subsc svc.subscriptionsMutex.Lock() sub := svc.subscriptions[subscription.Uuid] svc.subscriptionsMutex.Unlock() - err := sub.Relay.Publish(ctx, *subscription.RequestEvent) + err := sub.Relay.Publish(ctx, *subscription.RequestEvent.SignedEvent) if err != nil { // TODO: notify user about publish failure svc.Logger.WithError(err).WithFields(logrus.Fields{ @@ -781,7 +778,7 @@ func (svc *Service) publishRequestEvent(ctx context.Context, subscription *Subsc "wallet_pubkey": walletPubkey, "client_pubkey": clientPubkey, }).Info("Published request event successfully") - subscription.RequestEventDB.State = REQUEST_EVENT_PUBLISH_CONFIRMED + subscription.RequestEvent.State = REQUEST_EVENT_PUBLISH_CONFIRMED } } @@ -796,14 +793,14 @@ func (svc *Service) handleResponseEvent(event *nostr.Event, subscription *Subscr "relay_url": subscription.RelayUrl, }).Info("Received response event") if (subscription.RequestEvent != nil) { - subscription.RequestEventDB.ResponseReceivedAt = time.Now() - svc.db.Save(&subscription.RequestEventDB) + subscription.RequestEvent.ResponseReceivedAt = time.Now() + svc.db.Save(&subscription.RequestEvent) } responseEvent := ResponseEvent{ NostrId: event.ID, Content: event.Content, RepliedAt: event.CreatedAt.Time(), - RequestId: &subscription.RequestEventDB.ID, + RequestId: &subscription.RequestEvent.ID, } svc.db.Save(&responseEvent) if subscription.WebhookUrl != "" { @@ -956,8 +953,8 @@ func getPubkeys(subscription *Subscription) (string, string) { clientPubkey := "" if (subscription.RequestEvent != nil) { - walletPubkey = getWalletPubkey(&subscription.RequestEvent.Tags) - clientPubkey = subscription.RequestEvent.PubKey + walletPubkey = getWalletPubkey(&subscription.RequestEvent.SignedEvent.Tags) + clientPubkey = subscription.RequestEvent.SignedEvent.PubKey } return walletPubkey, clientPubkey