Этот коммит содержится в:
Ibrahim Serdar Acikgoz
2022-04-04 14:03:39 +03:00
коммит произвёл GitHub
родитель b1b9774efa
Коммит 97d3368a98
16 изменённых файлов: 173 добавлений и 188 удалений

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

@@ -28,7 +28,7 @@ import (
"github.com/mattermost/morph/drivers"
ms "github.com/mattermost/morph/drivers/mysql"
ps "github.com/mattermost/morph/drivers/postgres"
mbindata "github.com/mattermost/morph/sources/go_bindata"
mbindata "github.com/mattermost/morph/sources/embedded"
)
//go:embed migrations
@@ -113,7 +113,6 @@ func (ds *DatabaseStore) initializeConfigurationsTable() error {
if err != nil {
return err
}
defer src.Close()
cfg := drivers.Config{
MigrationsTable: migrationsTableName,

2
go.mod
Просмотреть файл

@@ -63,7 +63,7 @@ require (
github.com/mattermost/gziphandler v0.0.1
github.com/mattermost/ldap v0.0.0-20201202150706-ee0e6284187d
github.com/mattermost/logr/v2 v2.0.15
github.com/mattermost/morph v0.0.0-20220222074146-cff3f12ff131
github.com/mattermost/morph v0.0.0-20220401091636-39f834798da8
github.com/mattermost/rsc v0.0.0-20160330161541-bbaefb05eaa0
github.com/mattn/go-runewidth v0.0.13 // indirect
github.com/mattn/go-sqlite3 v2.0.3+incompatible // indirect

4
go.sum
Просмотреть файл

@@ -1003,8 +1003,8 @@ github.com/mattermost/ldap v0.0.0-20201202150706-ee0e6284187d h1:/RJ/UV7M5c7L2TQ
github.com/mattermost/ldap v0.0.0-20201202150706-ee0e6284187d/go.mod h1:HLbgMEI5K131jpxGazJ97AxfPDt31osq36YS1oxFQPQ=
github.com/mattermost/logr/v2 v2.0.15 h1:+WNbGcsc3dBao65eXlceB6dTILNJRIrvubnsTl3zBew=
github.com/mattermost/logr/v2 v2.0.15/go.mod h1:mpPp935r5dIkFDo2y9Q87cQWhFR/4xXpNh0k/y8Hmwg=
github.com/mattermost/morph v0.0.0-20220222074146-cff3f12ff131 h1:agJMxBP8LV0nyV90PZ/BHmmjNyvzTWqR20wLwiXHx14=
github.com/mattermost/morph v0.0.0-20220222074146-cff3f12ff131/go.mod h1:jxM3g1bx+k2Thz7jofcHguBS8TZn5Pc+o5MGmORObhw=
github.com/mattermost/morph v0.0.0-20220401091636-39f834798da8 h1:gwliVjCTqAC01mSCNqa5nJ/4MmGq50vrjsottIhQ4d8=
github.com/mattermost/morph v0.0.0-20220401091636-39f834798da8/go.mod h1:jxM3g1bx+k2Thz7jofcHguBS8TZn5Pc+o5MGmORObhw=
github.com/mattermost/rsc v0.0.0-20160330161541-bbaefb05eaa0 h1:G9tL6JXRBMzjuD1kkBtcnd42kUiT6QDwxfFYu7adM6o=
github.com/mattermost/rsc v0.0.0-20160330161541-bbaefb05eaa0/go.mod h1:nV5bfVpT//+B1RPD2JvRnxbkLmJEYXmRaaVl15fsXjs=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=

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

@@ -27,7 +27,7 @@ import (
_ "github.com/golang-migrate/migrate/v4/source/file"
"github.com/jmoiron/sqlx"
"github.com/lib/pq"
mbindata "github.com/mattermost/morph/sources/go_bindata"
mbindata "github.com/mattermost/morph/sources/embedded"
"github.com/pkg/errors"
"github.com/mattermost/mattermost-server/v6/db"
@@ -956,7 +956,6 @@ func (ss *SqlStore) migrate(direction migrationDirection) error {
if err != nil {
return err
}
defer src.Close()
var driver drivers.Driver
switch ss.DriverName() {

4
vendor/github.com/mattermost/morph/README.md сгенерированный поставляемый
Просмотреть файл

@@ -20,10 +20,10 @@ import (
"github.com/mattermost/morph"
"github.com/mattermost/morph/drivers/mysql"
bindata "github.com/mattermost/morph/sources/go_bindata"
"github.com/mattermost/morph/sources/embedded"
)
src, err := bindata.WithInstance(&bindata.AssetSource{
src, err := embedded.WithInstance(&embedded.AssetSource{
Names: []string{}, // add migration file names
AssetFunc: func(name string) ([]byte, error) {
return []byte{}, nil // should return the file contents

7
vendor/github.com/mattermost/morph/drivers/lock.go сгенерированный поставляемый
Просмотреть файл

@@ -63,14 +63,13 @@ func NextWaitInterval(lastWaitInterval time.Duration, err error) time.Duration {
}
type Locker interface {
Lock() error
Unlock() error
// LockWithContext locks m unless the context is canceled. If the mutex is already locked by any other
// Lock locks m unless the context is canceled. If the mutex is already locked by any other
// instance, including the current one, the calling goroutine blocks until the mutex can be locked,
// or the context is canceled.
//
// The mutex is locked only if a nil error is returned.
LockWithContext(ctx context.Context) error
Lock(ctx context.Context) error
Unlock() error
}
type Lockable interface {

19
vendor/github.com/mattermost/morph/drivers/logger.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,19 @@
package drivers
import "fmt"
type Logger interface {
Printf(format string, v ...interface{})
Println(v ...interface{})
}
type DefaultLogger struct {
}
func (DefaultLogger) Printf(format string, v ...interface{}) {
fmt.Printf(format, v...)
}
func (DefaultLogger) Println(v ...interface{}) {
fmt.Println(v...)
}

67
vendor/github.com/mattermost/morph/drivers/mysql/lock.go сгенерированный поставляемый
Просмотреть файл

@@ -8,6 +8,7 @@ import (
"sync"
"time"
ms "github.com/go-sql-driver/mysql"
"github.com/mattermost/morph/drivers"
)
@@ -26,12 +27,14 @@ type Mutex struct {
stopRefresh chan bool
refreshDone chan bool
conn *sql.Conn
logger drivers.Logger
}
// NewMutex creates a mutex with the given key name.
//
// returns error if key is empty.
func NewMutex(key string, driver drivers.Driver) (*Mutex, error) {
func NewMutex(key string, driver drivers.Driver, logger drivers.Logger) (*Mutex, error) {
key, err := drivers.MakeLockKey(key)
if err != nil {
return nil, err
@@ -56,8 +59,9 @@ func NewMutex(key string, driver drivers.Driver) (*Mutex, error) {
}
return &Mutex{
key: key,
conn: conn,
key: key,
conn: conn,
logger: logger,
}, nil
}
@@ -68,10 +72,16 @@ func (m *Mutex) tryLock(ctx context.Context) (bool, error) {
if err != nil {
return false, err
}
defer m.finalizeTx(tx)
query := fmt.Sprintf("INSERT INTO %s (Id, ExpireAt) VALUES (?, ?)", drivers.MutexTableName)
if _, err := tx.Exec(query, m.key, now.Add(drivers.TTL).Unix()); err != nil {
err2 := m.releaseLock(tx, now)
if mysqlErr, ok := err.(*ms.MySQLError); ok && mysqlErr.Number == 1062 {
m.logger.Println("DB is locked, going to try acquire the lock if it is expired.")
}
m.finalizeTx(tx)
err2 := m.releaseLock(ctx, now)
if err2 == nil { // lock has been released due to expiration
return true, nil
}
@@ -81,27 +91,25 @@ func (m *Mutex) tryLock(ctx context.Context) (bool, error) {
err = tx.Commit()
if err != nil {
if txErr := tx.Rollback(); txErr != nil {
return false, txErr
}
return false, err
}
return true, nil
}
func (m *Mutex) releaseLock(tx *sql.Tx, t time.Time) error {
func (m *Mutex) releaseLock(ctx context.Context, t time.Time) error {
tx, err := m.conn.BeginTx(ctx, nil)
if err != nil {
return err
}
defer m.finalizeTx(tx)
e, err := m.getExpireAt(tx)
if err != nil {
return err
}
if t.Unix() < e {
if txErr := tx.Rollback(); txErr != nil {
return fmt.Errorf("could not rollback: %w", txErr)
}
return errors.New("could not release the lock")
}
@@ -112,10 +120,6 @@ func (m *Mutex) releaseLock(tx *sql.Tx, t time.Time) error {
err = tx.Commit()
if err != nil {
if txErr := tx.Rollback(); txErr != nil {
return fmt.Errorf("could not rollback transaction: %w", txErr)
}
return fmt.Errorf("unable to set new expireat for mutex: %w", err)
}
@@ -127,10 +131,6 @@ func (m *Mutex) getExpireAt(tx *sql.Tx) (int64, error) {
query := fmt.Sprintf("SELECT ExpireAt FROM %s WHERE Id = ?", drivers.MutexTableName)
err := tx.QueryRow(query, m.key).Scan(&expireAt)
if err != nil {
if txErr := tx.Rollback(); txErr != nil {
return -1, fmt.Errorf("could not rollback: %w", txErr)
}
return -1, fmt.Errorf("failed to fetch mutex from db: %w", err)
}
@@ -143,6 +143,7 @@ func (m *Mutex) refreshLock(ctx context.Context) error {
if err != nil {
return err
}
defer m.finalizeTx(tx)
e, err := m.getExpireAt(tx)
if err != nil {
@@ -157,28 +158,18 @@ func (m *Mutex) refreshLock(ctx context.Context) error {
err = tx.Commit()
if err != nil {
if txErr := tx.Rollback(); txErr != nil {
return fmt.Errorf("could not rollback: %w", txErr)
}
return fmt.Errorf("unable to refresh expireat for mutex: %w", err)
}
return nil
}
// Lock locks m. If the mutex is already locked by any other morph instance, including the current one,
// the calling goroutine blocks until the mutex can be locked.
func (m *Mutex) Lock() error {
return m.LockWithContext(context.Background())
}
// LockWithContext locks m unless the context is canceled. If the mutex is already locked by any other
// Lock locks m unless the context is canceled. If the mutex is already locked by any other
// instance, including the current one, the calling goroutine blocks until the mutex can be locked,
// or the context is canceled.
//
// The mutex is locked only if a nil error is returned.
func (m *Mutex) LockWithContext(ctx context.Context) error {
func (m *Mutex) Lock(ctx context.Context) error {
var waitInterval time.Duration
for {
@@ -248,16 +239,18 @@ func (m *Mutex) Unlock() error {
func executeTx(tx *sql.Tx, query string, args ...interface{}) error {
if _, err := tx.Exec(query, args...); err != nil {
if txErr := tx.Rollback(); txErr != nil {
return fmt.Errorf("could not rollback transaction: %w", txErr)
}
return err
}
return nil
}
func (m *Mutex) finalizeTx(tx *sql.Tx) {
if err := tx.Rollback(); err != nil && err != sql.ErrTxDone {
m.logger.Printf("failed to rollback transaction: %s", err)
}
}
// noCopy may be embedded into structs which must not be copied
// after the first use.
//

67
vendor/github.com/mattermost/morph/drivers/postgres/lock.go сгенерированный поставляемый
Просмотреть файл

@@ -8,6 +8,7 @@ import (
"sync"
"time"
"github.com/lib/pq"
"github.com/mattermost/morph/drivers"
)
@@ -26,12 +27,14 @@ type Mutex struct {
stopRefresh chan bool
refreshDone chan bool
conn *sql.Conn
logger drivers.Logger
}
// NewMutex creates a mutex with the given key name.
//
// returns error if key is empty.
func NewMutex(key string, driver drivers.Driver) (*Mutex, error) {
func NewMutex(key string, driver drivers.Driver, logger drivers.Logger) (*Mutex, error) {
key, err := drivers.MakeLockKey(key)
if err != nil {
return nil, err
@@ -56,8 +59,9 @@ func NewMutex(key string, driver drivers.Driver) (*Mutex, error) {
}
return &Mutex{
key: key,
conn: conn,
key: key,
conn: conn,
logger: logger,
}, nil
}
@@ -68,10 +72,16 @@ func (m *Mutex) tryLock(ctx context.Context) (bool, error) {
if err != nil {
return false, err
}
defer m.finalizeTx(tx)
query := fmt.Sprintf("INSERT INTO %s (id, expireat) VALUES ($1, $2)", drivers.MutexTableName)
if _, err := tx.Exec(query, m.key, now.Add(drivers.TTL).Unix()); err != nil {
err2 := m.releaseLock(tx, now)
if pqErr, ok := err.(*pq.Error); ok && pqErr.Code == "23505" {
m.logger.Println("DB is locked, going to try acquire the lock if it is expired.")
}
m.finalizeTx(tx)
err2 := m.releaseLock(ctx, now)
if err2 == nil { // lock has been released due to expiration
return true, nil
}
@@ -81,27 +91,25 @@ func (m *Mutex) tryLock(ctx context.Context) (bool, error) {
err = tx.Commit()
if err != nil {
if txErr := tx.Rollback(); txErr != nil {
return false, txErr
}
return false, err
}
return true, nil
}
func (m *Mutex) releaseLock(tx *sql.Tx, t time.Time) error {
func (m *Mutex) releaseLock(ctx context.Context, t time.Time) error {
tx, err := m.conn.BeginTx(ctx, nil)
if err != nil {
return err
}
defer m.finalizeTx(tx)
e, err := m.getExpireAt(tx)
if err != nil {
return err
}
if t.Unix() < e {
if txErr := tx.Rollback(); txErr != nil {
return fmt.Errorf("could not rollback: %w", txErr)
}
return errors.New("could not release the lock")
}
@@ -112,10 +120,6 @@ func (m *Mutex) releaseLock(tx *sql.Tx, t time.Time) error {
err = tx.Commit()
if err != nil {
if txErr := tx.Rollback(); txErr != nil {
return fmt.Errorf("could not rollback transaction: %w", txErr)
}
return fmt.Errorf("unable to set new expireat for mutex: %w", err)
}
@@ -127,10 +131,6 @@ func (m *Mutex) getExpireAt(tx *sql.Tx) (int64, error) {
query := fmt.Sprintf("SELECT expireat FROM %s WHERE id = $1", drivers.MutexTableName)
err := tx.QueryRow(query, m.key).Scan(&expireAt)
if err != nil {
if txErr := tx.Rollback(); txErr != nil {
return -1, fmt.Errorf("could not rollback: %w", txErr)
}
return -1, fmt.Errorf("failed to fetch mutex from db: %w", err)
}
@@ -143,6 +143,7 @@ func (m *Mutex) refreshLock(ctx context.Context) error {
if err != nil {
return err
}
defer m.finalizeTx(tx)
e, err := m.getExpireAt(tx)
if err != nil {
@@ -157,28 +158,18 @@ func (m *Mutex) refreshLock(ctx context.Context) error {
err = tx.Commit()
if err != nil {
if txErr := tx.Rollback(); txErr != nil {
return fmt.Errorf("could not rollback: %w", txErr)
}
return fmt.Errorf("unable to refresh expireat for mutex: %w", err)
}
return nil
}
// Lock locks m. If the mutex is already locked by any other morph instance, including the current one,
// the calling goroutine blocks until the mutex can be locked.
func (m *Mutex) Lock() error {
return m.LockWithContext(context.Background())
}
// LockWithContext locks m unless the context is canceled. If the mutex is already locked by any other
// Lock locks m unless the context is canceled. If the mutex is already locked by any other
// instance, including the current one, the calling goroutine blocks until the mutex can be locked,
// or the context is canceled.
//
// The mutex is locked only if a nil error is returned.
func (m *Mutex) LockWithContext(ctx context.Context) error {
func (m *Mutex) Lock(ctx context.Context) error {
var waitInterval time.Duration
for {
@@ -248,16 +239,18 @@ func (m *Mutex) Unlock() error {
func executeTx(tx *sql.Tx, query string, args ...interface{}) error {
if _, err := tx.Exec(query, args...); err != nil {
if txErr := tx.Rollback(); txErr != nil {
return fmt.Errorf("could not rollback transaction: %w", txErr)
}
return err
}
return nil
}
func (m *Mutex) finalizeTx(tx *sql.Tx) {
if err := tx.Rollback(); err != nil && err != sql.ErrTxDone {
m.logger.Printf("failed to rollback transaction: %s", err)
}
}
// noCopy may be embedded into structs which must not be copied
// after the first use.
//

8
vendor/github.com/mattermost/morph/morph.go сгенерированный поставляемый
Просмотреть файл

@@ -18,8 +18,8 @@ import (
ms "github.com/mattermost/morph/drivers/mysql"
ps "github.com/mattermost/morph/drivers/postgres"
_ "github.com/mattermost/morph/sources/embedded"
_ "github.com/mattermost/morph/sources/file"
_ "github.com/mattermost/morph/sources/go_bindata"
)
var migrationProgressStart = "== %s: migrating ================================================="
@@ -99,9 +99,9 @@ func New(ctx context.Context, driver drivers.Driver, source sources.Source, opti
var err error
switch impl.DriverName() {
case "mysql":
mx, err = ms.NewMutex(engine.config.LockKey, driver)
mx, err = ms.NewMutex(engine.config.LockKey, driver, engine.config.Logger)
case "postgres":
mx, err = ps.NewMutex(engine.config.LockKey, driver)
mx, err = ps.NewMutex(engine.config.LockKey, driver, engine.config.Logger)
default:
err = errors.New("driver does not support locking")
}
@@ -110,7 +110,7 @@ func New(ctx context.Context, driver drivers.Driver, source sources.Source, opti
}
engine.mutex = mx
err = mx.LockWithContext(ctx)
err = mx.Lock(ctx)
if err != nil {
return nil, err
}

73
vendor/github.com/mattermost/morph/sources/embedded/README.md сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,73 @@
# embedded source
This source reads migrations from embedded files, for example using
[go-bindata](github.com/go-bindata/go-bindata) or go embed feature.
## go embed usage
To read the embedded data, create a migration source through the
`WithInstance` method and then instantiate `morph`:
```go
import (
"embed"
"path/filepath"
"github.com/mattermost/morph"
"github.com/mattermost/morph/sources/embedded"
)
//go:embed testfiles
var assets embed.FS
func main() {
dirEntries, err := assets.ReadDir("testfiles")
if err != nil {
panic(err)
}
assetNames := make([]string, len(dirEntries))
for i, dirEntry := range dirEntries {
assetNames[i] = dirEntry.Name()
}
res := embedded.Resource(assetNames, func(name string) ([]byte, error) {
return assets.ReadFile(filepath.Join("testfiles", name))
})
src, err := embedded.WithInstance(res)
if err != nil {
panic(err)
}
// create the morph instance from the source and driver
m := morph.NewFromConnURL("postgres://...", src, opts)
}
```
## go-bindata usage
To read the embedded data, create a migration source through the
`WithInstance` method and then instantiate `morph`:
```go
import (
"github.com/mattermost/morph"
"github.com/mattermost/morph/sources/embedded"
"github.com/mattermost/morph/sources/embedded/testdata"
)
func main() {
res := embedded.Resource(testdata.AssetNames(), func(name string) ([]byte, error) {
return testdata.Asset(name)
})
src, err := embedded.WithInstance(res)
if err != nil {
panic(err)
}
// create the morph instance from the source and driver
m := morph.NewFromConnURL("postgres://...", src, opts)
}
```

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

@@ -1,4 +1,4 @@
package bindata
package embedded
import (
"bytes"
@@ -23,21 +23,13 @@ type AssetSource struct {
AssetFunc AssetFunc
}
func init() {
sources.Register("go-bindata", &Bindata{})
}
type Bindata struct {
type Embedded struct {
assetSource *AssetSource
migrations []*models.Migration
}
func (b *Bindata) Open(url string) (sources.Source, error) {
return nil, fmt.Errorf("not implemented")
}
func WithInstance(assetSource *AssetSource) (sources.Source, error) {
b := &Bindata{
b := &Embedded{
assetSource: assetSource,
migrations: []*models.Migration{},
}
@@ -59,10 +51,6 @@ func WithInstance(assetSource *AssetSource) (sources.Source, error) {
return b, nil
}
func (b *Bindata) Close() error {
return nil
}
func (b *Bindata) Migrations() []*models.Migration {
func (b *Embedded) Migrations() []*models.Migration {
return b.migrations
}

11
vendor/github.com/mattermost/morph/sources/file/file.go сгенерированный поставляемый
Просмотреть файл

@@ -7,20 +7,15 @@ import (
"path/filepath"
"github.com/mattermost/morph/models"
"github.com/mattermost/morph/sources"
)
func init() {
sources.Register("file", &File{})
}
type File struct {
url string
path string
migrations []*models.Migration
}
func (f *File) Open(sourceURL string) (sources.Source, error) {
func Open(sourceURL string) (*File, error) {
uri, err := url.Parse(sourceURL)
if err != nil {
return nil, err
@@ -96,10 +91,6 @@ func (f *File) readMigrations() error {
return nil
}
func (f *File) Close() error {
return nil
}
func (f *File) Migrations() []*models.Migration {
return f.migrations
}

31
vendor/github.com/mattermost/morph/sources/go_bindata/README.md сгенерированный поставляемый
Просмотреть файл

@@ -1,31 +0,0 @@
# go-bindata source
This source reads migrations from a
[go-bindata](github.com/go-bindata/go-bindata) embedded binary file.
## Usage
To read the embedded data, create a migration source through the
`WithInstance` method and then instantiate `morph`:
```go
import (
"github.com/mattermost/morph"
"github.com/mattermost/morph/sources/go_bindata"
"github.com/mattermost/morph/sources/go_bindata/testdata"
)
func main() {
res := bindata.Resource(testdata.AssetNames(), func(name string) ([]byte, error) {
return testdata.Asset(name)
})
src, err := bindata.WithInstance(res)
if err != nil {
panic(err)
}
// create the morph instance from the source and driver
m := morph.NewFromConnURL("postgres://...", src, opts)
}
```

38
vendor/github.com/mattermost/morph/sources/source.go сгенерированный поставляемый
Просмотреть файл

@@ -1,47 +1,9 @@
package sources
import (
"fmt"
"sync"
"github.com/mattermost/morph/models"
)
var sourcesMu sync.RWMutex
var registeredSources = make(map[string]Source)
type Source interface {
Open(sourceURL string) (source Source, err error)
Close() (err error)
Migrations() (migrations []*models.Migration)
}
func Register(name string, source Source) {
sourcesMu.Lock()
defer sourcesMu.Unlock()
registeredSources[name] = source
}
func List() []string {
sourcesMu.Lock()
defer sourcesMu.Unlock()
sources := make([]string, 0, len(registeredSources))
for source := range registeredSources {
sources = append(sources, source)
}
return sources
}
func Open(sourceName, sourceURL string) (Source, error) {
sourcesMu.RLock()
source, ok := registeredSources[sourceName]
sourcesMu.RUnlock()
if !ok {
return nil, fmt.Errorf("unsupported source %q found", sourceName)
}
return source.Open(sourceURL)
}

4
vendor/modules.txt поставляемый
Просмотреть файл

@@ -404,7 +404,7 @@ github.com/mattermost/logr/v2
github.com/mattermost/logr/v2/config
github.com/mattermost/logr/v2/formatters
github.com/mattermost/logr/v2/targets
# github.com/mattermost/morph v0.0.0-20220222074146-cff3f12ff131
# github.com/mattermost/morph v0.0.0-20220401091636-39f834798da8
## explicit
github.com/mattermost/morph
github.com/mattermost/morph/drivers
@@ -412,8 +412,8 @@ github.com/mattermost/morph/drivers/mysql
github.com/mattermost/morph/drivers/postgres
github.com/mattermost/morph/models
github.com/mattermost/morph/sources
github.com/mattermost/morph/sources/embedded
github.com/mattermost/morph/sources/file
github.com/mattermost/morph/sources/go_bindata
# github.com/mattermost/rsc v0.0.0-20160330161541-bbaefb05eaa0
## explicit
github.com/mattermost/rsc/gf256