Migrate Plugin.SaveOrUpdate to sync by default (#11592)
Этот коммит содержится в:
коммит произвёл
Jesús Espino
родитель
e209a7acb4
Коммит
ce61681c92
@@ -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)
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user