Migrate Plugin.SaveOrUpdate to sync by default (#11592)

Этот коммит содержится в:
Rodrigo Villablanca Vásquez
2019-07-09 09:08:28 -04:00
коммит произвёл Jesús Espino
родитель e209a7acb4
Коммит ce61681c92
6 изменённых файлов: 68 добавлений и 57 удалений

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

@@ -34,9 +34,9 @@ func (a *App) SetPluginKeyWithExpiry(pluginId string, key string, value []byte,
ExpireAt: expireInSeconds, ExpireAt: expireInSeconds,
} }
if result := <-a.Srv.Store.Plugin().SaveOrUpdate(kv); result.Err != nil { if _, err := a.Srv.Store.Plugin().SaveOrUpdate(kv); err != nil {
mlog.Error("Failed to set plugin key value", mlog.String("plugin_id", pluginId), mlog.String("key", key), mlog.Err(result.Err)) mlog.Error("Failed to set plugin key value", mlog.String("plugin_id", pluginId), mlog.String("key", key), mlog.Err(err))
return result.Err return err
} }
// Clean up a previous entry using the hashed key, if it exists. // Clean up a previous entry using the hashed key, if it exists.

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

@@ -66,8 +66,8 @@ func TestPluginKeyValueStore(t *testing.T) {
ExpireAt: 0, ExpireAt: 0,
} }
result := <-th.App.Srv.Store.Plugin().SaveOrUpdate(kv) _, err = th.App.Srv.Store.Plugin().SaveOrUpdate(kv)
assert.Nil(t, result.Err) assert.Nil(t, err)
// Test fetch by keyname (this key does not exist but hashed key will be used for lookup) // Test fetch by keyname (this key does not exist but hashed key will be used for lookup)
ret, err = th.App.GetPluginKey(pluginId, "key2") ret, err = th.App.GetPluginKey(pluginId, "key2")

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

@@ -36,18 +36,16 @@ func NewSqlPluginStore(sqlStore SqlStore) store.PluginStore {
func (ps SqlPluginStore) CreateIndexesIfNotExists() { func (ps SqlPluginStore) CreateIndexesIfNotExists() {
} }
func (ps SqlPluginStore) SaveOrUpdate(kv *model.PluginKeyValue) store.StoreChannel { func (ps SqlPluginStore) SaveOrUpdate(kv *model.PluginKeyValue) (*model.PluginKeyValue, *model.AppError) {
return store.Do(func(result *store.StoreResult) { if err := kv.IsValid(); err != nil {
if result.Err = kv.IsValid(); result.Err != nil { return nil, err
return
} }
if ps.DriverName() == model.DATABASE_DRIVER_POSTGRES { if ps.DriverName() == model.DATABASE_DRIVER_POSTGRES {
// Unfortunately PostgreSQL pre-9.5 does not have an atomic upsert, so we use // Unfortunately PostgreSQL pre-9.5 does not have an atomic upsert, so we use
// separate update and insert queries to accomplish our upsert // separate update and insert queries to accomplish our upsert
if rowsAffected, err := ps.GetMaster().Update(kv); err != nil { if rowsAffected, err := ps.GetMaster().Update(kv); err != nil {
result.Err = model.NewAppError("SqlPluginStore.SaveOrUpdate", "store.sql_plugin_store.save.app_error", nil, err.Error(), http.StatusInternalServerError) return nil, model.NewAppError("SqlPluginStore.SaveOrUpdate", "store.sql_plugin_store.save.app_error", nil, err.Error(), http.StatusInternalServerError)
return
} else if rowsAffected == 0 { } else if rowsAffected == 0 {
// No rows were affected by the update, so let's try an insert // No rows were affected by the update, so let's try an insert
if err := ps.GetMaster().Insert(kv); err != nil { if err := ps.GetMaster().Insert(kv); err != nil {
@@ -55,20 +53,17 @@ func (ps SqlPluginStore) SaveOrUpdate(kv *model.PluginKeyValue) store.StoreChann
// valid race and we can report success. Otherwise we have a real error and // valid race and we can report success. Otherwise we have a real error and
// need to return it // need to return it
if !IsUniqueConstraintError(err, []string{"PRIMARY", "PluginId", "Key", "PKey"}) { if !IsUniqueConstraintError(err, []string{"PRIMARY", "PluginId", "Key", "PKey"}) {
result.Err = model.NewAppError("SqlPluginStore.SaveOrUpdate", "store.sql_plugin_store.save.app_error", nil, err.Error(), http.StatusInternalServerError) return nil, model.NewAppError("SqlPluginStore.SaveOrUpdate", "store.sql_plugin_store.save.app_error", nil, err.Error(), http.StatusInternalServerError)
return
} }
} }
} }
} else if ps.DriverName() == model.DATABASE_DRIVER_MYSQL { } else if ps.DriverName() == model.DATABASE_DRIVER_MYSQL {
if _, err := ps.GetMaster().Exec("INSERT INTO PluginKeyValueStore (PluginId, PKey, PValue, ExpireAt) VALUES(:PluginId, :Key, :Value, :ExpireAt) ON DUPLICATE KEY UPDATE PValue = :Value, ExpireAt = :ExpireAt", map[string]interface{}{"PluginId": kv.PluginId, "Key": kv.Key, "Value": kv.Value, "ExpireAt": kv.ExpireAt}); err != nil { if _, err := ps.GetMaster().Exec("INSERT INTO PluginKeyValueStore (PluginId, PKey, PValue, ExpireAt) VALUES(:PluginId, :Key, :Value, :ExpireAt) ON DUPLICATE KEY UPDATE PValue = :Value, ExpireAt = :ExpireAt", map[string]interface{}{"PluginId": kv.PluginId, "Key": kv.Key, "Value": kv.Value, "ExpireAt": kv.ExpireAt}); err != nil {
result.Err = model.NewAppError("SqlPluginStore.SaveOrUpdate", "store.sql_plugin_store.save.app_error", nil, err.Error(), http.StatusInternalServerError) return nil, model.NewAppError("SqlPluginStore.SaveOrUpdate", "store.sql_plugin_store.save.app_error", nil, err.Error(), http.StatusInternalServerError)
return
} }
} }
result.Data = kv return kv, nil
})
} }
func (ps SqlPluginStore) CompareAndSet(kv *model.PluginKeyValue, oldValue []byte) (bool, *model.AppError) { func (ps SqlPluginStore) CompareAndSet(kv *model.PluginKeyValue, oldValue []byte) (bool, *model.AppError) {

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

@@ -535,7 +535,7 @@ type UserAccessTokenStore interface {
} }
type PluginStore interface { type PluginStore interface {
SaveOrUpdate(keyVal *model.PluginKeyValue) StoreChannel SaveOrUpdate(keyVal *model.PluginKeyValue) (*model.PluginKeyValue, *model.AppError)
CompareAndSet(keyVal *model.PluginKeyValue, oldValue []byte) (bool, *model.AppError) CompareAndSet(keyVal *model.PluginKeyValue, oldValue []byte) (bool, *model.AppError)
Get(pluginId, key string) (*model.PluginKeyValue, *model.AppError) Get(pluginId, key string) (*model.PluginKeyValue, *model.AppError)
Delete(pluginId, key string) StoreChannel Delete(pluginId, key string) StoreChannel

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

@@ -135,17 +135,26 @@ func (_m *PluginStore) List(pluginId string, page int, perPage int) ([]string, *
} }
// SaveOrUpdate provides a mock function with given fields: keyVal // SaveOrUpdate provides a mock function with given fields: keyVal
func (_m *PluginStore) SaveOrUpdate(keyVal *model.PluginKeyValue) store.StoreChannel { func (_m *PluginStore) SaveOrUpdate(keyVal *model.PluginKeyValue) (*model.PluginKeyValue, *model.AppError) {
ret := _m.Called(keyVal) ret := _m.Called(keyVal)
var r0 store.StoreChannel var r0 *model.PluginKeyValue
if rf, ok := ret.Get(0).(func(*model.PluginKeyValue) store.StoreChannel); ok { if rf, ok := ret.Get(0).(func(*model.PluginKeyValue) *model.PluginKeyValue); ok {
r0 = rf(keyVal) r0 = rf(keyVal)
} else { } else {
if ret.Get(0) != nil { if ret.Get(0) != nil {
r0 = ret.Get(0).(store.StoreChannel) r0 = ret.Get(0).(*model.PluginKeyValue)
} }
} }
return r0 var r1 *model.AppError
if rf, ok := ret.Get(1).(func(*model.PluginKeyValue) *model.AppError); ok {
r1 = rf(keyVal)
} else {
if ret.Get(1) != nil {
r1 = ret.Get(1).(*model.AppError)
}
}
return r0, r1
} }

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

@@ -6,6 +6,8 @@ package storetest
import ( import (
"testing" "testing"
"github.com/stretchr/testify/require"
"github.com/mattermost/mattermost-server/model" "github.com/mattermost/mattermost-server/model"
"github.com/mattermost/mattermost-server/store" "github.com/mattermost/mattermost-server/store"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
@@ -27,8 +29,8 @@ func testPluginSaveGet(t *testing.T, ss store.Store) {
ExpireAt: 0, ExpireAt: 0,
} }
if result := <-ss.Plugin().SaveOrUpdate(kv); result.Err != nil { if _, err := ss.Plugin().SaveOrUpdate(kv); err != nil {
t.Fatal(result.Err) t.Fatal(err)
} }
defer func() { defer func() {
@@ -46,8 +48,8 @@ func testPluginSaveGet(t *testing.T, ss store.Store) {
// Try inserting when already exists // Try inserting when already exists
kv.Value = []byte(model.NewId()) kv.Value = []byte(model.NewId())
if result := <-ss.Plugin().SaveOrUpdate(kv); result.Err != nil { if _, err := ss.Plugin().SaveOrUpdate(kv); err != nil {
t.Fatal(result.Err) t.Fatal(err)
} }
if received, err := ss.Plugin().Get(kv.PluginId, kv.Key); err != nil { if received, err := ss.Plugin().Get(kv.PluginId, kv.Key); err != nil {
@@ -67,8 +69,8 @@ func testPluginSaveGetExpiry(t *testing.T, ss store.Store) {
ExpireAt: model.GetMillis() + 30000, ExpireAt: model.GetMillis() + 30000,
} }
if result := <-ss.Plugin().SaveOrUpdate(kv); result.Err != nil { if _, err := ss.Plugin().SaveOrUpdate(kv); err != nil {
t.Fatal(result.Err) t.Fatal(err)
} }
defer func() { defer func() {
@@ -91,8 +93,8 @@ func testPluginSaveGetExpiry(t *testing.T, ss store.Store) {
ExpireAt: model.GetMillis() - 5000, ExpireAt: model.GetMillis() - 5000,
} }
if result := <-ss.Plugin().SaveOrUpdate(kv); result.Err != nil { if _, err := ss.Plugin().SaveOrUpdate(kv); err != nil {
t.Fatal(result.Err) t.Fatal(err)
} }
defer func() { defer func() {
@@ -105,11 +107,12 @@ func testPluginSaveGetExpiry(t *testing.T, ss store.Store) {
} }
func testPluginDelete(t *testing.T, ss store.Store) { func testPluginDelete(t *testing.T, ss store.Store) {
kv := store.Must(ss.Plugin().SaveOrUpdate(&model.PluginKeyValue{ kv, err := ss.Plugin().SaveOrUpdate(&model.PluginKeyValue{
PluginId: model.NewId(), PluginId: model.NewId(),
Key: model.NewId(), Key: model.NewId(),
Value: []byte(model.NewId()), Value: []byte(model.NewId()),
})).(*model.PluginKeyValue) })
require.Nil(t, err)
if result := <-ss.Plugin().Delete(kv.PluginId, kv.Key); result.Err != nil { if result := <-ss.Plugin().Delete(kv.PluginId, kv.Key); result.Err != nil {
t.Fatal(result.Err) t.Fatal(result.Err)
@@ -119,17 +122,19 @@ func testPluginDelete(t *testing.T, ss store.Store) {
func testPluginDeleteAll(t *testing.T, ss store.Store) { func testPluginDeleteAll(t *testing.T, ss store.Store) {
pluginId := model.NewId() pluginId := model.NewId()
kv := store.Must(ss.Plugin().SaveOrUpdate(&model.PluginKeyValue{ kv, err := ss.Plugin().SaveOrUpdate(&model.PluginKeyValue{
PluginId: pluginId, PluginId: pluginId,
Key: model.NewId(), Key: model.NewId(),
Value: []byte(model.NewId()), Value: []byte(model.NewId()),
})).(*model.PluginKeyValue) })
require.Nil(t, err)
kv2 := store.Must(ss.Plugin().SaveOrUpdate(&model.PluginKeyValue{ kv2, err := ss.Plugin().SaveOrUpdate(&model.PluginKeyValue{
PluginId: pluginId, PluginId: pluginId,
Key: model.NewId(), Key: model.NewId(),
Value: []byte(model.NewId()), Value: []byte(model.NewId()),
})).(*model.PluginKeyValue) })
require.Nil(t, err)
if result := <-ss.Plugin().DeleteAllForPlugin(pluginId); result.Err != nil { if result := <-ss.Plugin().DeleteAllForPlugin(pluginId); result.Err != nil {
t.Fatal(result.Err) t.Fatal(result.Err)
@@ -147,19 +152,21 @@ func testPluginDeleteAll(t *testing.T, ss store.Store) {
func testPluginDeleteExpired(t *testing.T, ss store.Store) { func testPluginDeleteExpired(t *testing.T, ss store.Store) {
pluginId := model.NewId() pluginId := model.NewId()
kv := store.Must(ss.Plugin().SaveOrUpdate(&model.PluginKeyValue{ kv, err := ss.Plugin().SaveOrUpdate(&model.PluginKeyValue{
PluginId: pluginId, PluginId: pluginId,
Key: model.NewId(), Key: model.NewId(),
Value: []byte(model.NewId()), Value: []byte(model.NewId()),
ExpireAt: model.GetMillis() - 6000, ExpireAt: model.GetMillis() - 6000,
})).(*model.PluginKeyValue) })
require.Nil(t, err)
kv2 := store.Must(ss.Plugin().SaveOrUpdate(&model.PluginKeyValue{ kv2, err := ss.Plugin().SaveOrUpdate(&model.PluginKeyValue{
PluginId: pluginId, PluginId: pluginId,
Key: model.NewId(), Key: model.NewId(),
Value: []byte(model.NewId()), Value: []byte(model.NewId()),
ExpireAt: 0, ExpireAt: 0,
})).(*model.PluginKeyValue) })
require.Nil(t, err)
if result := <-ss.Plugin().DeleteAllExpired(); result.Err != nil { if result := <-ss.Plugin().DeleteAllExpired(); result.Err != nil {
t.Fatal(result.Err) t.Fatal(result.Err)