123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223 |
- // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
- // See LICENSE.txt for license information.
- package plugin
- import (
- "encoding/json"
- "strings"
- "github.com/pkg/errors"
- )
- // KVSetJSON implements Helpers.KVSetJSON.
- func (p *HelpersImpl) KVSetJSON(key string, value interface{}) error {
- err := p.ensureServerVersion("5.2.0")
- if err != nil {
- return err
- }
- data, err := json.Marshal(value)
- if err != nil {
- return err
- }
- appErr := p.API.KVSet(key, data)
- if appErr != nil {
- return appErr
- }
- return nil
- }
- // KVCompareAndSetJSON implements Helpers.KVCompareAndSetJSON.
- func (p *HelpersImpl) KVCompareAndSetJSON(key string, oldValue interface{}, newValue interface{}) (bool, error) {
- var err error
- err = p.ensureServerVersion("5.12.0")
- if err != nil {
- return false, err
- }
- var oldData, newData []byte
- if oldValue != nil {
- oldData, err = json.Marshal(oldValue)
- if err != nil {
- return false, errors.Wrap(err, "unable to marshal old value")
- }
- }
- if newValue != nil {
- newData, err = json.Marshal(newValue)
- if err != nil {
- return false, errors.Wrap(err, "unable to marshal new value")
- }
- }
- set, appErr := p.API.KVCompareAndSet(key, oldData, newData)
- if appErr != nil {
- return set, appErr
- }
- return set, nil
- }
- // KVCompareAndDeleteJSON implements Helpers.KVCompareAndDeleteJSON.
- func (p *HelpersImpl) KVCompareAndDeleteJSON(key string, oldValue interface{}) (bool, error) {
- var err error
- err = p.ensureServerVersion("5.16.0")
- if err != nil {
- return false, err
- }
- var oldData []byte
- if oldValue != nil {
- oldData, err = json.Marshal(oldValue)
- if err != nil {
- return false, errors.Wrap(err, "unable to marshal old value")
- }
- }
- deleted, appErr := p.API.KVCompareAndDelete(key, oldData)
- if appErr != nil {
- return deleted, appErr
- }
- return deleted, nil
- }
- // KVGetJSON implements Helpers.KVGetJSON.
- func (p *HelpersImpl) KVGetJSON(key string, value interface{}) (bool, error) {
- err := p.ensureServerVersion("5.2.0")
- if err != nil {
- return false, err
- }
- data, appErr := p.API.KVGet(key)
- if appErr != nil {
- return false, appErr
- }
- if data == nil {
- return false, nil
- }
- err = json.Unmarshal(data, value)
- if err != nil {
- return false, err
- }
- return true, nil
- }
- // KVSetWithExpiryJSON is a wrapper around KVSetWithExpiry to simplify atomically writing a JSON object with expiry to the key value store.
- func (p *HelpersImpl) KVSetWithExpiryJSON(key string, value interface{}, expireInSeconds int64) error {
- err := p.ensureServerVersion("5.6.0")
- if err != nil {
- return err
- }
- data, err := json.Marshal(value)
- if err != nil {
- return err
- }
- appErr := p.API.KVSetWithExpiry(key, data, expireInSeconds)
- if appErr != nil {
- return appErr
- }
- return nil
- }
- type kvListOptions struct {
- checkers []func(key string) (keep bool, err error)
- }
- func (o *kvListOptions) checkAll(key string) (keep bool, err error) {
- for _, check := range o.checkers {
- keep, err := check(key)
- if err != nil {
- return false, err
- }
- if !keep {
- return false, nil
- }
- }
- // key made it through all checkers
- return true, nil
- }
- // KVListOption represents a single input option for KVListWithOptions
- type KVListOption func(*kvListOptions)
- // WithPrefix only return keys that start with the given string.
- func WithPrefix(prefix string) KVListOption {
- return WithChecker(func(key string) (keep bool, err error) {
- return strings.HasPrefix(key, prefix), nil
- })
- }
- // WithChecker allows for a custom filter function to determine which keys to return.
- // Returning true will keep the key and false will filter it out. Returning an error
- // will halt KVListWithOptions immediately and pass the error up (with no other results).
- func WithChecker(f func(key string) (keep bool, err error)) KVListOption {
- return func(args *kvListOptions) {
- args.checkers = append(args.checkers, f)
- }
- }
- // kvListPerPage is the number of keys KVListWithOptions gets per request
- const kvListPerPage = 100
- // KVListWithOptions implements Helpers.KVListWithOptions.
- func (p *HelpersImpl) KVListWithOptions(options ...KVListOption) ([]string, error) {
- err := p.ensureServerVersion("5.6.0")
- if err != nil {
- return nil, err
- }
- // convert functional options into args struct
- args := &kvListOptions{}
- for _, opt := range options {
- opt(args)
- }
- ret := make([]string, 0)
- // get our keys a batch at a time, filter out the ones we don't want based on our args
- // any errors will hault the whole process and return the error raw
- for i := 0; ; i++ {
- keys, appErr := p.API.KVList(i, kvListPerPage)
- if appErr != nil {
- return nil, appErr
- }
- if len(args.checkers) == 0 {
- // no checkers, just append the whole block at once
- ret = append(ret, keys...)
- } else {
- // we have a filter, so check each key, all checkers must say key
- // for us to keep a key
- for _, key := range keys {
- keep, err := args.checkAll(key)
- if err != nil {
- return nil, err
- }
- if !keep {
- continue
- }
- // didn't get filtered out, add to our return
- ret = append(ret, key)
- }
- }
- if len(keys) < kvListPerPage {
- break
- }
- }
- return ret, nil
- }
|