200 lines
3.9 KiB
Go

package main
import (
"encoding/json"
"errors"
"github.com/larkox/mattermost-plugin-badges/badgesmodel"
)
const ATOMICRETRIES = 3
func (s *store) doAtomic(f func() (bool, error)) error {
done := false
for i := 0; i < ATOMICRETRIES; i++ {
var err error
done, err = f()
if err != nil {
return err
}
if done {
break
}
}
if !done {
return errors.New("too many attempts on atomic retry")
}
return nil
}
func (s *store) compareAndSet(key string, old []byte, value interface{}) (bool, error) {
data, err := json.Marshal(value)
if err != nil {
return false, err
}
done, appErr := s.api.KVCompareAndSet(key, old, data)
if appErr != nil {
return false, appErr
}
return done, nil
}
func (s *store) atomicRemoveBadge(bID badgesmodel.BadgeID) (bool, error) {
bb, data, err := s.getAllBadges()
if err != nil {
return false, err
}
for i, b := range bb {
if b.ID == bID {
bb = append(bb[:i], bb[i+1:]...)
break
}
}
return s.compareAndSet(KVKeyBadges, data, bb)
}
func (s *store) atomicRemoveBadgeFromOwnership(bID badgesmodel.BadgeID) (bool, error) {
ownership, data, err := s.getOwnershipList()
if err != nil {
return false, err
}
toDelete := []int{}
for i, o := range ownership {
if o.Badge == bID {
toDelete = append([]int{i}, toDelete...)
}
}
for _, index := range toDelete {
ownership = append(ownership[:index], ownership[index+1:]...)
}
return s.compareAndSet(KVKeyOwnership, data, ownership)
}
func (s *store) atomicAddBadge(b *badgesmodel.Badge) (bool, error) {
bb, data, err := s.getAllBadges()
if err != nil {
return false, err
}
bb = append(bb, b)
return s.compareAndSet(KVKeyBadges, data, bb)
}
func (s *store) atomicAddType(t *badgesmodel.BadgeTypeDefinition) (bool, error) {
tt, data, err := s.getAllTypes()
if err != nil {
return false, err
}
tt = append(tt, t)
return s.compareAndSet(KVKeyTypes, data, tt)
}
func (s *store) atomicAddBadgeToOwnership(o badgesmodel.Ownership, isMultiple bool) (shouldNotify bool, done bool, err error) {
ownership, data, err := s.getOwnershipList()
if err != nil {
return false, false, err
}
if !isMultiple && ownership.IsOwned(o.User, o.Badge) {
return false, true, nil
}
ownership = append(ownership, o)
done, err = s.compareAndSet(KVKeyOwnership, data, ownership)
return done, done, err
}
func (s *store) atomicUpdateType(t *badgesmodel.BadgeTypeDefinition) (bool, error) {
tt, data, err := s.getAllTypes()
if err != nil {
return false, err
}
found := false
for i, tOld := range tt {
if tOld.ID == t.ID {
tt[i] = t
found = true
break
}
}
if !found {
return false, errors.New("not found")
}
return s.compareAndSet(KVKeyTypes, data, tt)
}
func (s *store) atomicUpdateBadge(b *badgesmodel.Badge) (bool, error) {
bb, data, err := s.getAllBadges()
if err != nil {
return false, err
}
found := false
for i, bOld := range bb {
if bOld.ID == b.ID {
bb[i] = b
found = true
break
}
}
if !found {
return false, errors.New("not found")
}
return s.compareAndSet(KVKeyBadges, data, bb)
}
func (s *store) atomicAddSubscription(toAdd badgesmodel.Subscription) (bool, error) {
subs, data, err := s.getAllSubscriptions()
if err != nil {
return false, err
}
for _, sub := range subs {
if sub.ChannelID == toAdd.ChannelID && sub.TypeID == toAdd.TypeID {
return true, nil
}
}
subs = append(subs, toAdd)
return s.compareAndSet(KVKeySubscriptions, data, subs)
}
func (s *store) atomicRemoveSubscription(toRemove badgesmodel.Subscription) (bool, error) {
subs, data, err := s.getAllSubscriptions()
if err != nil {
return false, err
}
found := false
for i, sub := range subs {
if sub.ChannelID == toRemove.ChannelID && sub.TypeID == toRemove.TypeID {
subs = append(subs[:i], subs[i+1:]...)
found = true
break
}
}
if !found {
return true, nil
}
return s.compareAndSet(KVKeySubscriptions, data, subs)
}