mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-15 09:22:43 +03:00
b875d95a75
Co-authored-by: Aravind K P <8335904+scriptonist@users.noreply.github.com> GitOrigin-RevId: 8f6791d5fd51d011623361ac2f5994c8badb50bf
142 lines
5.0 KiB
Go
142 lines
5.0 KiB
Go
package source
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
nurl "net/url"
|
|
"sync"
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
)
|
|
|
|
var driversMu sync.RWMutex
|
|
var drivers = make(map[string]Driver)
|
|
|
|
// Driver is the interface every source driver must implement.
|
|
//
|
|
// How to implement a source driver?
|
|
// 1. Implement this interface.
|
|
// 2. Optionally, add a function named `WithInstance`.
|
|
// This function should accept an existing source instance and a Config{} struct
|
|
// and return a driver instance.
|
|
// 3. Add a test that calls source/testing.go:Test()
|
|
// 4. Add own tests for Open(), WithInstance() (when provided) and Close().
|
|
// All other functions are tested by tests in source/testing.
|
|
// Saves you some time and makes sure all source drivers behave the same way.
|
|
// 5. Call Register in init().
|
|
//
|
|
// Guidelines:
|
|
// * All configuration input must come from the URL string in func Open()
|
|
// or the Config{} struct in WithInstance. Don't os.Getenv().
|
|
// * Drivers are supposed to be read only.
|
|
// * Ideally don't load any contents (into memory) in Open or WithInstance.
|
|
type Driver interface {
|
|
// Open returns a new driver instance configured with parameters
|
|
// coming from the URL string. Migrate will call this function
|
|
// only once per instance.
|
|
Open(url string, logger *log.Logger) (Driver, error)
|
|
|
|
// Close closes the underlying source instance managed by the driver.
|
|
// Migrate will call this function only once per instance.
|
|
Close() error
|
|
|
|
// Scan scans the local migration files
|
|
Scan() error
|
|
|
|
// Default Parser to be used for scanning the file system
|
|
DefaultParser(Parser)
|
|
|
|
// First returns the very first migration version available to the driver.
|
|
// Migrate will call this function multiple times.
|
|
// If there is no version available, it must return os.ErrNotExist.
|
|
First() (version uint64, err error)
|
|
|
|
// GetLocalVersion returns the latest version available in migrations folder
|
|
GetLocalVersion() (version uint64, err error)
|
|
|
|
// Get all unapplied migrations present in local directory
|
|
GetUnappliedMigrations(version uint64) (versions []uint64)
|
|
|
|
// Prev returns the previous version for a given version available to the driver.
|
|
// Migrate will call this function multiple times.
|
|
// If there is no previous version available, it must return os.ErrNotExist.
|
|
Prev(version uint64) (prevVersion uint64, err error)
|
|
|
|
// Next returns the next version for a given version available to the driver.
|
|
// Migrate will call this function multiple times.
|
|
// If there is no next version available, it must return os.ErrNotExist.
|
|
Next(version uint64) (nextVersion uint64, err error)
|
|
|
|
GetDirections(version uint64) map[Direction]bool
|
|
|
|
// ReadUp returns the UP migration body and an identifier that helps
|
|
// finding this migration in the source for a given version.
|
|
// If there is no up migration available for this version,
|
|
// it must return os.ErrNotExist.
|
|
// Do not start reading, just return the ReadCloser!
|
|
ReadUp(version uint64) (r io.ReadCloser, identifier string, fileName string, err error)
|
|
|
|
// ReadUp returns the UP migration body and an identifier that helps
|
|
// finding this migration in the source for a given version.
|
|
// If there is no up migration available for this version,
|
|
// it must return os.ErrNotExist.
|
|
// Do not start reading, just return the ReadCloser!
|
|
ReadMetaUp(version uint64) (r io.ReadCloser, identifier string, fileName string, err error)
|
|
|
|
// ReadDown returns the DOWN migration body and an identifier that helps
|
|
// finding this migration in the source for a given version.
|
|
// If there is no down migration available for this version,
|
|
// it must return os.ErrNotExist.
|
|
// Do not start reading, just return the ReadCloser!
|
|
ReadDown(version uint64) (r io.ReadCloser, identifier string, fileName string, err error)
|
|
|
|
// ReadDown returns the DOWN migration body and an identifier that helps
|
|
// finding this migration in the source for a given version.
|
|
// If there is no down migration available for this version,
|
|
// it must return os.ErrNotExist.
|
|
// Do not start reading, just return the ReadCloser!
|
|
ReadMetaDown(version uint64) (r io.ReadCloser, identifier string, fileName string, err error)
|
|
|
|
// ReadName returns an name that helps
|
|
// finding this migration in the source for a given version
|
|
ReadName(version uint64) (name string)
|
|
}
|
|
|
|
// Open returns a new driver instance.
|
|
func Open(url string, logger *log.Logger) (Driver, error) {
|
|
u, err := nurl.Parse(url)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if u.Scheme == "" {
|
|
return nil, fmt.Errorf("source driver: invalid URL scheme")
|
|
}
|
|
|
|
driversMu.RLock()
|
|
d, ok := drivers[u.Scheme]
|
|
driversMu.RUnlock()
|
|
if !ok {
|
|
return nil, fmt.Errorf("source driver: unknown driver %v (forgotten import?)", u.Scheme)
|
|
}
|
|
|
|
if logger == nil {
|
|
logger = log.New()
|
|
}
|
|
|
|
return d.Open(url, logger)
|
|
}
|
|
|
|
// Register globally registers a driver.
|
|
func Register(name string, driver Driver) {
|
|
driversMu.Lock()
|
|
defer driversMu.Unlock()
|
|
if driver == nil {
|
|
panic("Register driver is nil")
|
|
}
|
|
if _, dup := drivers[name]; dup {
|
|
panic("Register called twice for driver " + name)
|
|
}
|
|
drivers[name] = driver
|
|
}
|