From 456b53ae724c60360e922e65354ffeccbedfdfd5 Mon Sep 17 00:00:00 2001 From: Daniel Date: Wed, 31 Jul 2019 22:33:19 +0200 Subject: [PATCH] Add GUID to notifications and improve put/save handling --- Gopkg.lock | 9 ++++ Gopkg.toml | 4 ++ notifications/database.go | 89 ++++++++++++++++++++++++----------- notifications/notification.go | 20 +++++--- 4 files changed, 87 insertions(+), 35 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index ca14576..7c42392 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -118,6 +118,14 @@ revision = "ba968bfe8b2f7e042a574c888954fccecfa385b4" version = "v0.8.1" +[[projects]] + digest = "1:274f67cb6fed9588ea2521ecdac05a6d62a8c51c074c1fccc6a49a40ba80e925" + name = "github.com/satori/go.uuid" + packages = ["."] + pruneopts = "UT" + revision = "f58768cc1a7a7e77a3bd49e98cdd21419399b6a3" + version = "v1.2.0" + [[projects]] branch = "master" digest = "1:f1ee4af7c43f206d87f13644636e3710a05e499a084a32ec2cc7d8aa25cef1aa" @@ -246,6 +254,7 @@ "github.com/google/renameio", "github.com/gorilla/mux", "github.com/gorilla/websocket", + "github.com/satori/go.uuid", "github.com/seehuhn/fortuna", "github.com/tevino/abool", "github.com/tidwall/gjson", diff --git a/Gopkg.toml b/Gopkg.toml index c597e4c..76053e0 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -84,3 +84,7 @@ [prune] go-tests = true unused-packages = true + +[[constraint]] + name = "github.com/satori/go.uuid" + version = "1.2.0" diff --git a/notifications/database.go b/notifications/database.go index 9779aae..927ef72 100644 --- a/notifications/database.go +++ b/notifications/database.go @@ -43,6 +43,26 @@ type StorageInterface struct { storage.InjectBase } +func registerAsDatabase() error { + _, err := database.Register(&database.Database{ + Name: "notifications", + Description: "Notifications", + StorageType: "injected", + PrimaryAPI: "", + }) + if err != nil { + return err + } + + controller, err := database.InjectDatabase("notifications", &StorageInterface{}) + if err != nil { + return err + } + + dbController = controller + return nil +} + // Get returns a database record. func (s *StorageInterface) Get(key string) (record.Record, error) { notsLock.RLock() @@ -78,6 +98,10 @@ func (s *StorageInterface) processQuery(q *query.Query, it *iterator.Iterator) { // send all notifications for _, n := range nots { + if n.Meta().IsDeleted() { + continue + } + if q.MatchesKey(n.DatabaseKey()) && q.MatchesRecord(n) { it.Next <- n } @@ -86,26 +110,6 @@ func (s *StorageInterface) processQuery(q *query.Query, it *iterator.Iterator) { it.Finish(nil) } -func registerAsDatabase() error { - _, err := database.Register(&database.Database{ - Name: "notifications", - Description: "Notifications", - StorageType: "injected", - PrimaryAPI: "", - }) - if err != nil { - return err - } - - controller, err := database.InjectDatabase("notifications", &StorageInterface{}) - if err != nil { - return err - } - - dbController = controller - return nil -} - // Put stores a record in the database. func (s *StorageInterface) Put(r record.Record) error { // record is already locked! @@ -135,25 +139,54 @@ func updateNotificationFromDatabasePut(n *Notification, key string) { origN, ok := nots[key] notsLock.RUnlock() + // ignore if already deleted + if ok && origN.Meta().IsDeleted() { + ok = false + } + if ok { // existing notification, update selected action ID only n.Lock() defer n.Unlock() - if n.SelectedActionID != "" { - log.Tracef("notifications: user selected action for %s: %s", n.ID, n.SelectedActionID) - go origN.SelectAndExecuteAction(n.SelectedActionID) - } } else { // accept new notification as is - notsLock.Lock() - nots[key] = n - notsLock.Unlock() + n.Save() + // set var for action processing + origN = n + } + + // select action, if not yet already handled + if n.SelectedActionID != "" && n.Responded == 0 { + log.Tracef("notifications: user selected action for %s: %s", n.ID, n.SelectedActionID) + origN.SelectAndExecuteAction(n.SelectedActionID) } } // Delete deletes a record from the database. func (s *StorageInterface) Delete(key string) error { - return ErrNoDelete + notsLock.Lock() + defer notsLock.Unlock() + + // transform key + if strings.HasPrefix(key, "all/") { + key = strings.TrimPrefix(key, "all/") + } else { + return storage.ErrNotFound + } + + // get notification + n, ok := nots[key] + if !ok { + return storage.ErrNotFound + } + n.Lock() + defer n.Unlock() + + // delete + n.Meta().Delete() + delete(nots, n.ID) + + return nil } // ReadOnly returns whether the database is read only. diff --git a/notifications/notification.go b/notifications/notification.go index 59d28b7..5d51543 100644 --- a/notifications/notification.go +++ b/notifications/notification.go @@ -7,6 +7,8 @@ import ( "github.com/safing/portbase/database/record" "github.com/safing/portbase/log" + + uuid "github.com/satori/go.uuid" ) // Notification types @@ -20,7 +22,9 @@ const ( type Notification struct { record.Base - ID string + ID string + GUID string + Message string // MessageTemplate string // MessageData []string @@ -62,12 +66,6 @@ func Get(id string) *Notification { return nil } -// Init initializes a Notification and returns it. -func (n *Notification) Init() *Notification { - n.Created = time.Now().Unix() - return n -} - // Save saves the notification and returns it. func (n *Notification) Save() *Notification { notsLock.Lock() @@ -75,6 +73,14 @@ func (n *Notification) Save() *Notification { n.Lock() defer n.Unlock() + // initialize + if n.Created == 0 { + n.Created = time.Now().Unix() + } + if n.GUID == "" { + n.GUID = uuid.NewV4().String() + } + // check key if n.DatabaseKey() == "" { n.SetKey(fmt.Sprintf("notifications:all/%s", n.ID))