From a28a1f3bf46fec671e9a69f04cfbafe20f0a1967 Mon Sep 17 00:00:00 2001 From: Serhii Olshanivskyi Date: Sat, 2 Dec 2023 16:53:20 +0200 Subject: [PATCH 1/2] feat: add endpoint for updating watcher token --- pkg/firebase/cloud-messaging/service.go | 4 +- services/watcher/handler.go | 32 ++++++++++++++-- services/watcher/repository.go | 1 - services/watcher/service.go | 51 ++++++++++++++++++------- services/watcher/types.go | 4 +- services/watcher/watcher.go | 5 +++ 6 files changed, 76 insertions(+), 21 deletions(-) diff --git a/pkg/firebase/cloud-messaging/service.go b/pkg/firebase/cloud-messaging/service.go index 3e153e7..c581db1 100644 --- a/pkg/firebase/cloud-messaging/service.go +++ b/pkg/firebase/cloud-messaging/service.go @@ -3,8 +3,8 @@ package cloudmessaging import ( "context" "errors" - "strconv" "fmt" + "strconv" "firebase.google.com/go/messaging" ) @@ -41,7 +41,7 @@ func (s *service) SendMessage(ctx context.Context, title, body, pushToken string case bool: androidData[key] = strconv.FormatBool(v) case float64: - androidData[key] = strconv.FormatFloat(v, 'f', -1, 64) + androidData[key] = strconv.FormatFloat(v, 'f', -1, 64) } } diff --git a/services/watcher/handler.go b/services/watcher/handler.go index 5e334f3..5937a20 100644 --- a/services/watcher/handler.go +++ b/services/watcher/handler.go @@ -30,6 +30,8 @@ func (h *Handler) SetupRoutes(router fiber.Router) { router.Delete("/watcher-addresses", h.DeleteWatcherAddressesHandler) router.Post("/explorer-callback", h.WatcherCallbackHandler) + + router.Put("/push-token/:oldPushToken/:newPushToken", h.UpdateWatcherPushTokenHandler) } func (h *Handler) GetWatcherHandler(c *fiber.Ctx) error { @@ -49,7 +51,6 @@ func (h *Handler) GetWatcherHandler(c *fiber.Ctx) error { return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": err.Error()}) } - return c.JSON(watcher) } @@ -159,14 +160,39 @@ func (h *Handler) DeleteWatcherAddressesHandler(c *fiber.Ctx) error { return c.JSON(fiber.Map{"status": "OK"}) } +type UpdateWatcherPushToken struct { + OldPushToken string `json:"old_push_token" validate:"required"` + NewPushToken string `json:"new_push_token" validate:"required"` +} + +func (h *Handler) UpdateWatcherPushTokenHandler(c *fiber.Ctx) error { + var reqBody UpdateWatcherPushToken + + if err := c.BodyParser(&reqBody); err != nil { + return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ + "message": err.Error(), + }) + } + + if err := Validate(reqBody); err != nil { + return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": err.Error()}) + } + + if err := h.service.UpdateWatcherPushToken(c.Context(), reqBody.OldPushToken, reqBody.NewPushToken); err != nil { + return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": err.Error()}) + } + + return nil +} + type WatcherCallbackItem struct { Address string `json:"address" validate:"required"` TxHash string `json:"txHash" validate:"required"` } type WatcherCallback struct { - Id string `json:"id" validate:"required"` - Items []WatcherCallbackItem `json:"items" validate:"required"` + Id string `json:"id" validate:"required"` + Items []WatcherCallbackItem `json:"items" validate:"required"` } func (h *Handler) WatcherCallbackHandler(c *fiber.Ctx) error { diff --git a/services/watcher/repository.go b/services/watcher/repository.go index 1662d0e..baf1e93 100644 --- a/services/watcher/repository.go +++ b/services/watcher/repository.go @@ -82,7 +82,6 @@ func (r *repository) GetWatcherList(ctx context.Context, filters bson.M, page in watchers = append(watchers, &watcher) } - // Check for any errors that occurred during iteration if err := cur.Err(); err != nil { r.logger.Errorf("cursor iteration error: %v", err) diff --git a/services/watcher/service.go b/services/watcher/service.go index 19eaf15..7ab1bdb 100644 --- a/services/watcher/service.go +++ b/services/watcher/service.go @@ -42,10 +42,11 @@ type Service interface { UpdateWatcher(ctx context.Context, pushToken string, addresses *[]string, threshold *float64, txNotification, priceNotification *string) error DeleteWatcher(ctx context.Context, pushToken string) error DeleteWatcherAddresses(ctx context.Context, pushToken string, addresses []string) error + UpdateWatcherPushToken(ctx context.Context, olpPushToken string, newPushToken string) error } type watchers struct { - watchers map[string]*Watcher + watchers map[string]*Watcher } type service struct { @@ -98,7 +99,7 @@ func NewService( explorerUrl: explorerUrl, tokenPriceUrl: tokenPriceUrl, - callbackUrl: callbackUrl, + callbackUrl: callbackUrl, explorerToken: explorerToken, cachedChan: make(map[string]chan struct{}), @@ -123,7 +124,7 @@ func (self *watchers) Remove(pushToken string) { } func (self *watchers) IsEmpty() bool { - return self.watchers == nil || len(self.watchers) == 0 + return self.watchers == nil || len(self.watchers) == 0 } func (s *service) Init(ctx context.Context) error { @@ -169,7 +170,7 @@ func (s *service) keepAlive(ctx context.Context) { } if watchers == nil { - break + break } for _, watcher := range watchers { @@ -225,7 +226,7 @@ func (s *service) keepAlive(ctx context.Context) { time.Sleep(5 * time.Second) continue } - break; + break } time.Sleep(30 * time.Second) tries = 6 @@ -418,9 +419,9 @@ func (s *service) TransactionWatch(ctx context.Context, address string, txHash s if err != nil { s.logger.Errorf("TransactionWatch cloudMessagingSvc.SendMessage error %v\n", err) if err.Error() == "http error status: 404; reason: app instance has been unregistered; code: registration-token-not-registered; details: Requested entity was not found." { - s.mx.RLock() - watchers.Remove(watcher.PushToken) //TODO: check if this is needed - s.mx.RUnlock() + s.mx.RLock() + watchers.Remove(watcher.PushToken) //TODO: check if this is needed + s.mx.RUnlock() } } @@ -464,7 +465,6 @@ func (s *service) GetWatcher(ctx context.Context, pushToken string) (*Watcher, e return nil, errors.New("watcher not found") } - s.mx.Lock() s.cachedWatcher[encodePushToken] = watcher s.mx.Unlock() @@ -488,7 +488,6 @@ func (s *service) CreateWatcher(ctx context.Context, pushToken string) error { return errors.New("watcher for this address and token already exist") } - watcher, err := NewWatcher(encodePushToken) if err != nil { return err @@ -511,7 +510,6 @@ func (s *service) CreateWatcher(ctx context.Context, pushToken string) error { return err } - s.mx.Lock() s.cachedWatcher[watcher.PushToken] = watcher s.mx.Unlock() @@ -530,7 +528,6 @@ func (s *service) UpdateWatcher(ctx context.Context, pushToken string, addresses return errors.New("watcher not found") } - if addresses != nil && len(*addresses) > 0 { var req bytes.Buffer req.WriteString("{\"id\":\"") @@ -694,6 +691,34 @@ func (s *service) DeleteWatcherAddresses(ctx context.Context, pushToken string, return nil } +func (s *service) UpdateWatcherPushToken(ctx context.Context, olpPushToken string, newPushToken string) error { + encodePushToken := base64.StdEncoding.EncodeToString([]byte(olpPushToken)) + + watcher, err := s.GetWatcher(ctx, olpPushToken) + if err != nil { + s.logger.Errorf("UpdateWatcherPushToken GetWatcher error %v\n", err) + return err + } + if watcher == nil { + s.logger.Errorf("UpdateWatcherPushToken watcher not found\n") + return err + } + + watcher.SetPushToken(base64.StdEncoding.EncodeToString([]byte(newPushToken))) + + if err := s.repository.UpdateWatcher(ctx, watcher); err != nil { + s.logger.Errorf("UpdateWatcherPushToken repository.UpdateWatcher error %v\n", err) + return err + } + + s.mx.Lock() + delete(s.cachedWatcher, encodePushToken) + s.cachedWatcher[watcher.PushToken] = watcher + s.mx.Unlock() + + return nil +} + func (s *service) setUpStopChanAndStartWatchers(ctx context.Context, watcher *Watcher) { s.mx.Lock() stopChan := make(chan struct{}) @@ -794,5 +819,5 @@ func (s *service) doRequest(url string, body io.Reader, res interface{}) error { } func (self *service) GetExplorerId() string { - return self.explorerToken + return self.explorerToken } diff --git a/services/watcher/types.go b/services/watcher/types.go index 4dbb25b..36c3c20 100644 --- a/services/watcher/types.go +++ b/services/watcher/types.go @@ -13,7 +13,7 @@ type Tx struct { To string `json:"to"` Hash string `json:"hash"` Value struct { - Ether float64 `json:"ether"` + Ether float64 `json:"ether"` Symbol *string `json:"symbol,omitempty"` } `json:"value"` @@ -26,7 +26,7 @@ type ApiAddressData struct { } type ApiTxData struct { - Data []Tx `json:"data"` + Data []Tx `json:"data"` } type PriceData struct { diff --git a/services/watcher/watcher.go b/services/watcher/watcher.go index 53c9202..071b249 100644 --- a/services/watcher/watcher.go +++ b/services/watcher/watcher.go @@ -129,3 +129,8 @@ func (w *Watcher) SetPriceNotification(v string) { w.PriceNotification = v w.UpdatedAt = time.Now() } + +func (w *Watcher) SetPushToken(v string) { + w.PushToken = v + w.UpdatedAt = time.Now() +} From 5280246865f47ae6367c30025f3bc20a5a89192a Mon Sep 17 00:00:00 2001 From: Serhii Olshanivskyi Date: Sat, 2 Dec 2023 17:35:30 +0200 Subject: [PATCH 2/2] feat: change API endpoint signature --- services/watcher/handler.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/watcher/handler.go b/services/watcher/handler.go index 5937a20..f5a4e82 100644 --- a/services/watcher/handler.go +++ b/services/watcher/handler.go @@ -31,7 +31,7 @@ func (h *Handler) SetupRoutes(router fiber.Router) { router.Post("/explorer-callback", h.WatcherCallbackHandler) - router.Put("/push-token/:oldPushToken/:newPushToken", h.UpdateWatcherPushTokenHandler) + router.Put("/push-token", h.UpdateWatcherPushTokenHandler) } func (h *Handler) GetWatcherHandler(c *fiber.Ctx) error {