MM-16821 - Add a KVCompareAndDelete to the plugin API (#11804)

* Implement KVCompareAndDelete and KVCompareAndDeleteJSON

* Add tests for KVCompareAndDelete

* Update minimum server version

* Handle nil value on CompareAndSet so that it deletes it

* Fix comments

* Tweaks from PR comments

* Go back to deleted, err
Этот коммит содержится в:
Gervasio Marchand
2019-08-21 23:25:38 -03:00
коммит произвёл Jesse Hallam
родитель f8ad9f3b8f
Коммит 11b0a20d7d
13 изменённых файлов: 281 добавлений и 0 удалений

Просмотреть файл

@@ -71,6 +71,11 @@ func (ps SqlPluginStore) CompareAndSet(kv *model.PluginKeyValue, oldValue []byte
return false, err
}
if kv.Value == nil {
// Setting a key to nil is the same as removing it
return ps.CompareAndDelete(kv, oldValue)
}
if oldValue == nil {
// Insert if oldValue is nil
if err := ps.GetMaster().Insert(kv); err != nil {
@@ -111,6 +116,37 @@ func (ps SqlPluginStore) CompareAndSet(kv *model.PluginKeyValue, oldValue []byte
return true, nil
}
func (ps SqlPluginStore) CompareAndDelete(kv *model.PluginKeyValue, oldValue []byte) (bool, *model.AppError) {
if err := kv.IsValid(); err != nil {
return false, err
}
if oldValue == nil {
// nil can't be stored. Return showing that we didn't do anything
return false, nil
}
deleteResult, err := ps.GetMaster().Exec(
`DELETE FROM PluginKeyValueStore WHERE PluginId = :PluginId AND PKey = :Key AND PValue = :Old`,
map[string]interface{}{
"PluginId": kv.PluginId,
"Key": kv.Key,
"Old": oldValue,
},
)
if err != nil {
return false, model.NewAppError("SqlPluginStore.CompareAndDelete", "store.sql_plugin_store.save.app_error", nil, err.Error(), http.StatusInternalServerError)
}
if rowsAffected, err := deleteResult.RowsAffected(); err != nil {
return false, model.NewAppError("SqlPluginStore.CompareAndDelete", "store.sql_plugin_store.save.app_error", nil, err.Error(), http.StatusInternalServerError)
} else if rowsAffected == 0 {
return false, nil
}
return true, nil
}
func (ps SqlPluginStore) Get(pluginId, key string) (*model.PluginKeyValue, *model.AppError) {
var kv *model.PluginKeyValue
currentTime := model.GetMillis()

Просмотреть файл

@@ -520,6 +520,7 @@ type UserAccessTokenStore interface {
type PluginStore interface {
SaveOrUpdate(keyVal *model.PluginKeyValue) (*model.PluginKeyValue, *model.AppError)
CompareAndSet(keyVal *model.PluginKeyValue, oldValue []byte) (bool, *model.AppError)
CompareAndDelete(keyVal *model.PluginKeyValue, oldValue []byte) (bool, *model.AppError)
Get(pluginId, key string) (*model.PluginKeyValue, *model.AppError)
Delete(pluginId, key string) *model.AppError
DeleteAllForPlugin(PluginId string) *model.AppError

Просмотреть файл

@@ -12,6 +12,29 @@ type PluginStore struct {
mock.Mock
}
// CompareAndDelete provides a mock function with given fields: keyVal, oldValue
func (_m *PluginStore) CompareAndDelete(keyVal *model.PluginKeyValue, oldValue []byte) (bool, *model.AppError) {
ret := _m.Called(keyVal, oldValue)
var r0 bool
if rf, ok := ret.Get(0).(func(*model.PluginKeyValue, []byte) bool); ok {
r0 = rf(keyVal, oldValue)
} else {
r0 = ret.Get(0).(bool)
}
var r1 *model.AppError
if rf, ok := ret.Get(1).(func(*model.PluginKeyValue, []byte) *model.AppError); ok {
r1 = rf(keyVal, oldValue)
} else {
if ret.Get(1) != nil {
r1 = ret.Get(1).(*model.AppError)
}
}
return r0, r1
}
// CompareAndSet provides a mock function with given fields: keyVal, oldValue
func (_m *PluginStore) CompareAndSet(keyVal *model.PluginKeyValue, oldValue []byte) (bool, *model.AppError) {
ret := _m.Called(keyVal, oldValue)