mirror of
https://github.com/hasura/graphql-engine.git
synced 2025-01-05 22:34:22 +03:00
optimise migrate api for console on cli (#2895)
This commit is contained in:
parent
0a64ef99b5
commit
5f3294f4a0
@ -3,7 +3,6 @@ package commands
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/fatih/color"
|
"github.com/fatih/color"
|
||||||
@ -11,9 +10,9 @@ import (
|
|||||||
"github.com/gin-contrib/static"
|
"github.com/gin-contrib/static"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/hasura/graphql-engine/cli"
|
"github.com/hasura/graphql-engine/cli"
|
||||||
|
"github.com/hasura/graphql-engine/cli/migrate"
|
||||||
"github.com/hasura/graphql-engine/cli/migrate/api"
|
"github.com/hasura/graphql-engine/cli/migrate/api"
|
||||||
"github.com/hasura/graphql-engine/cli/util"
|
"github.com/hasura/graphql-engine/cli/util"
|
||||||
"github.com/hasura/graphql-engine/cli/version"
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"github.com/skratchdot/open-golang/open"
|
"github.com/skratchdot/open-golang/open"
|
||||||
@ -85,14 +84,9 @@ func (o *consoleOptions) run() error {
|
|||||||
gin.SetMode(gin.ReleaseMode)
|
gin.SetMode(gin.ReleaseMode)
|
||||||
|
|
||||||
// An Engine instance with the Logger and Recovery middleware already attached.
|
// An Engine instance with the Logger and Recovery middleware already attached.
|
||||||
r := gin.New()
|
g := gin.New()
|
||||||
|
|
||||||
r.Use(allowCors())
|
g.Use(allowCors())
|
||||||
|
|
||||||
// My Router struct
|
|
||||||
router := &cRouter{
|
|
||||||
r,
|
|
||||||
}
|
|
||||||
|
|
||||||
if o.EC.Version == nil {
|
if o.EC.Version == nil {
|
||||||
return errors.New("cannot validate version, object is nil")
|
return errors.New("cannot validate version, object is nil")
|
||||||
@ -103,7 +97,18 @@ func (o *consoleOptions) run() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
router.setRoutes(o.EC.ServerConfig.ParsedEndpoint, o.EC.ServerConfig.AdminSecret, o.EC.MigrationDir, metadataPath, o.EC.Logger, o.EC.Version)
|
t, err := newMigrate(o.EC.MigrationDir, o.EC.ServerConfig.ParsedEndpoint, o.EC.ServerConfig.AdminSecret, o.EC.Logger, o.EC.Version, false)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// My Router struct
|
||||||
|
r := &cRouter{
|
||||||
|
g,
|
||||||
|
t,
|
||||||
|
}
|
||||||
|
|
||||||
|
r.setRoutes(o.EC.MigrationDir, metadataPath, o.EC.Logger)
|
||||||
|
|
||||||
consoleTemplateVersion := o.EC.Version.GetConsoleTemplateVersion()
|
consoleTemplateVersion := o.EC.Version.GetConsoleTemplateVersion()
|
||||||
consoleAssetsVersion := o.EC.Version.GetConsoleAssetsVersion()
|
consoleAssetsVersion := o.EC.Version.GetConsoleAssetsVersion()
|
||||||
@ -134,7 +139,7 @@ func (o *consoleOptions) run() error {
|
|||||||
o.WG = wg
|
o.WG = wg
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
err = router.Run(o.Address + ":" + o.APIPort)
|
err = r.router.Run(o.Address + ":" + o.APIPort)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
o.EC.Logger.WithError(err).Errorf("error listening on port %s", o.APIPort)
|
o.EC.Logger.WithError(err).Errorf("error listening on port %s", o.APIPort)
|
||||||
}
|
}
|
||||||
@ -171,15 +176,16 @@ func (o *consoleOptions) run() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type cRouter struct {
|
type cRouter struct {
|
||||||
*gin.Engine
|
router *gin.Engine
|
||||||
|
migrate *migrate.Migrate
|
||||||
}
|
}
|
||||||
|
|
||||||
func (router *cRouter) setRoutes(nurl *url.URL, adminSecret, migrationDir, metadataFile string, logger *logrus.Logger, v *version.Version) {
|
func (r *cRouter) setRoutes(migrationDir, metadataFile string, logger *logrus.Logger) {
|
||||||
apis := router.Group("/apis")
|
apis := r.router.Group("/apis")
|
||||||
{
|
{
|
||||||
apis.Use(setLogger(logger))
|
apis.Use(setLogger(logger))
|
||||||
apis.Use(setFilePath(migrationDir))
|
apis.Use(setFilePath(migrationDir))
|
||||||
apis.Use(setDataPath(nurl, getAdminSecretHeaderName(v), adminSecret))
|
apis.Use(setMigrate(r.migrate))
|
||||||
// Migrate api endpoints and middleware
|
// Migrate api endpoints and middleware
|
||||||
migrateAPIs := apis.Group("/migrate")
|
migrateAPIs := apis.Group("/migrate")
|
||||||
{
|
{
|
||||||
@ -198,11 +204,9 @@ func (router *cRouter) setRoutes(nurl *url.URL, adminSecret, migrationDir, metad
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func setDataPath(nurl *url.URL, adminSecretHeader, adminSecret string) gin.HandlerFunc {
|
func setMigrate(t *migrate.Migrate) gin.HandlerFunc {
|
||||||
return func(c *gin.Context) {
|
return func(c *gin.Context) {
|
||||||
host := getDataPath(nurl, adminSecretHeader, adminSecret)
|
c.Set("migrate", t)
|
||||||
|
|
||||||
c.Set("dbpath", host)
|
|
||||||
c.Next()
|
c.Next()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package commands
|
package commands
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -19,7 +20,7 @@ func TestConsoleCmd(t *testing.T) {
|
|||||||
ec.Spinner = spinner.New(spinner.CharSets[7], 100*time.Millisecond)
|
ec.Spinner = spinner.New(spinner.CharSets[7], 100*time.Millisecond)
|
||||||
ec.ServerConfig = &cli.ServerConfig{
|
ec.ServerConfig = &cli.ServerConfig{
|
||||||
Endpoint: "http://localhost:8080",
|
Endpoint: "http://localhost:8080",
|
||||||
AdminSecret: "",
|
AdminSecret: os.Getenv("HASURA_GRAPHQL_TEST_ADMIN_SECRET"),
|
||||||
}
|
}
|
||||||
ec.MetadataFile = []string{"metadata.yaml"}
|
ec.MetadataFile = []string{"metadata.yaml"}
|
||||||
|
|
||||||
@ -33,7 +34,6 @@ func TestConsoleCmd(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("prepare failed: %v", err)
|
t.Fatalf("prepare failed: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
opts := &consoleOptions{
|
opts := &consoleOptions{
|
||||||
EC: ec,
|
EC: ec,
|
||||||
APIPort: "9693",
|
APIPort: "9693",
|
||||||
|
@ -57,7 +57,7 @@ type metadataApplyOptions struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (o *metadataApplyOptions) run() error {
|
func (o *metadataApplyOptions) run() error {
|
||||||
migrateDrv, err := newMigrate(o.EC.MigrationDir, o.EC.ServerConfig.ParsedEndpoint, o.EC.ServerConfig.AdminSecret, o.EC.Logger, o.EC.Version)
|
migrateDrv, err := newMigrate(o.EC.MigrationDir, o.EC.ServerConfig.ParsedEndpoint, o.EC.ServerConfig.AdminSecret, o.EC.Logger, o.EC.Version, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -61,7 +61,7 @@ type metadataClearOptions struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (o *metadataClearOptions) run() error {
|
func (o *metadataClearOptions) run() error {
|
||||||
migrateDrv, err := newMigrate(o.EC.MigrationDir, o.EC.ServerConfig.ParsedEndpoint, o.EC.ServerConfig.AdminSecret, o.EC.Logger, o.EC.Version)
|
migrateDrv, err := newMigrate(o.EC.MigrationDir, o.EC.ServerConfig.ParsedEndpoint, o.EC.ServerConfig.AdminSecret, o.EC.Logger, o.EC.Version, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -64,7 +64,7 @@ type metadataExportOptions struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (o *metadataExportOptions) run() error {
|
func (o *metadataExportOptions) run() error {
|
||||||
migrateDrv, err := newMigrate(o.EC.MigrationDir, o.EC.ServerConfig.ParsedEndpoint, o.EC.ServerConfig.AdminSecret, o.EC.Logger, o.EC.Version)
|
migrateDrv, err := newMigrate(o.EC.MigrationDir, o.EC.ServerConfig.ParsedEndpoint, o.EC.ServerConfig.AdminSecret, o.EC.Logger, o.EC.Version, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,7 @@ type metadataReloadOptions struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (o *metadataReloadOptions) run() error {
|
func (o *metadataReloadOptions) run() error {
|
||||||
migrateDrv, err := newMigrate(o.EC.MigrationDir, o.EC.ServerConfig.ParsedEndpoint, o.EC.ServerConfig.AdminSecret, o.EC.Logger, o.EC.Version)
|
migrateDrv, err := newMigrate(o.EC.MigrationDir, o.EC.ServerConfig.ParsedEndpoint, o.EC.ServerConfig.AdminSecret, o.EC.Logger, o.EC.Version, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -34,10 +34,10 @@ func NewMigrateCmd(ec *cli.ExecutionContext) *cobra.Command {
|
|||||||
return migrateCmd
|
return migrateCmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func newMigrate(dir string, db *url.URL, adminSecretValue string, logger *logrus.Logger, v *version.Version) (*migrate.Migrate, error) {
|
func newMigrate(dir string, db *url.URL, adminSecretValue string, logger *logrus.Logger, v *version.Version, isCmd bool) (*migrate.Migrate, error) {
|
||||||
dbURL := getDataPath(db, getAdminSecretHeaderName(v), adminSecretValue)
|
dbURL := getDataPath(db, getAdminSecretHeaderName(v), adminSecretValue)
|
||||||
fileURL := getFilePath(dir)
|
fileURL := getFilePath(dir)
|
||||||
t, err := migrate.New(fileURL.String(), dbURL.String(), true, logger)
|
t, err := migrate.New(fileURL.String(), dbURL.String(), isCmd, logger)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "cannot create migrate instance")
|
return nil, errors.Wrap(err, "cannot create migrate instance")
|
||||||
}
|
}
|
||||||
|
@ -71,7 +71,7 @@ func (o *migrateApplyOptions) run() error {
|
|||||||
return errors.Wrap(err, "error validating flags")
|
return errors.Wrap(err, "error validating flags")
|
||||||
}
|
}
|
||||||
|
|
||||||
migrateDrv, err := newMigrate(o.EC.MigrationDir, o.EC.ServerConfig.ParsedEndpoint, o.EC.ServerConfig.AdminSecret, o.EC.Logger, o.EC.Version)
|
migrateDrv, err := newMigrate(o.EC.MigrationDir, o.EC.ServerConfig.ParsedEndpoint, o.EC.ServerConfig.AdminSecret, o.EC.Logger, o.EC.Version, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -109,7 +109,7 @@ func (o *migrateCreateOptions) run() (version int64, err error) {
|
|||||||
|
|
||||||
var migrateDrv *migrate.Migrate
|
var migrateDrv *migrate.Migrate
|
||||||
if o.sqlServer || o.metaDataServer {
|
if o.sqlServer || o.metaDataServer {
|
||||||
migrateDrv, err = newMigrate(o.EC.MigrationDir, o.EC.ServerConfig.ParsedEndpoint, o.EC.ServerConfig.AdminSecret, o.EC.Logger, o.EC.Version)
|
migrateDrv, err = newMigrate(o.EC.MigrationDir, o.EC.ServerConfig.ParsedEndpoint, o.EC.ServerConfig.AdminSecret, o.EC.Logger, o.EC.Version, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, errors.Wrap(err, "cannot create migrate instance")
|
return 0, errors.Wrap(err, "cannot create migrate instance")
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,7 @@ type migrateStatusOptions struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (o *migrateStatusOptions) run() (*migrate.Status, error) {
|
func (o *migrateStatusOptions) run() (*migrate.Status, error) {
|
||||||
migrateDrv, err := newMigrate(o.EC.MigrationDir, o.EC.ServerConfig.ParsedEndpoint, o.EC.ServerConfig.AdminSecret, o.EC.Logger, o.EC.Version)
|
migrateDrv, err := newMigrate(o.EC.MigrationDir, o.EC.ServerConfig.ParsedEndpoint, o.EC.ServerConfig.AdminSecret, o.EC.Logger, o.EC.Version, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -4,39 +4,22 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/ghodss/yaml"
|
"github.com/ghodss/yaml"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/hasura/graphql-engine/cli/migrate"
|
"github.com/hasura/graphql-engine/cli/migrate"
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func MetadataAPI(c *gin.Context) {
|
func MetadataAPI(c *gin.Context) {
|
||||||
// Get File url
|
// Get migrate instance
|
||||||
sourcePtr, ok := c.Get("filedir")
|
migratePtr, ok := c.Get("migrate")
|
||||||
if !ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
sourceURL := sourcePtr.(*url.URL)
|
|
||||||
|
|
||||||
// Get hasuradb url
|
|
||||||
databasePtr, ok := c.Get("dbpath")
|
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert to url.URL
|
// Convert to url.URL
|
||||||
databaseURL := databasePtr.(*url.URL)
|
t := migratePtr.(*migrate.Migrate)
|
||||||
|
|
||||||
// Get Logger
|
|
||||||
loggerPtr, ok := c.Get("logger")
|
|
||||||
if !ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
logger := loggerPtr.(*logrus.Logger)
|
|
||||||
|
|
||||||
metadataFilePtr, ok := c.Get("metadataFile")
|
metadataFilePtr, ok := c.Get("metadataFile")
|
||||||
if !ok {
|
if !ok {
|
||||||
@ -44,17 +27,6 @@ func MetadataAPI(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
metadataFile := metadataFilePtr.(string)
|
metadataFile := metadataFilePtr.(string)
|
||||||
|
|
||||||
// Create new migrate
|
|
||||||
t, err := migrate.New(sourceURL.String(), databaseURL.String(), false, logger)
|
|
||||||
if err != nil {
|
|
||||||
if strings.HasPrefix(err.Error(), DataAPIError) {
|
|
||||||
c.JSON(http.StatusInternalServerError, &Response{Code: "data_api_error", Message: err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.JSON(http.StatusInternalServerError, &Response{Code: "internal_error", Message: err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Switch on request method
|
// Switch on request method
|
||||||
switch c.Request.Method {
|
switch c.Request.Method {
|
||||||
case "GET":
|
case "GET":
|
||||||
|
@ -32,14 +32,12 @@ type Request struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func MigrateAPI(c *gin.Context) {
|
func MigrateAPI(c *gin.Context) {
|
||||||
// Get File url
|
migratePtr, ok := c.Get("migrate")
|
||||||
sourcePtr, ok := c.Get("filedir")
|
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// Get File url
|
||||||
// Get hasuradb url
|
sourcePtr, ok := c.Get("filedir")
|
||||||
databasePtr, ok := c.Get("dbpath")
|
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -51,21 +49,10 @@ func MigrateAPI(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Convert to url.URL
|
// Convert to url.URL
|
||||||
databaseURL := databasePtr.(*url.URL)
|
t := migratePtr.(*migrate.Migrate)
|
||||||
sourceURL := sourcePtr.(*url.URL)
|
sourceURL := sourcePtr.(*url.URL)
|
||||||
logger := loggerPtr.(*logrus.Logger)
|
logger := loggerPtr.(*logrus.Logger)
|
||||||
|
|
||||||
// Create new migrate
|
|
||||||
t, err := migrate.New(sourceURL.String(), databaseURL.String(), false, logger)
|
|
||||||
if err != nil {
|
|
||||||
if strings.HasPrefix(err.Error(), DataAPIError) {
|
|
||||||
c.JSON(http.StatusInternalServerError, &Response{Code: "data_api_error", Message: err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.JSON(http.StatusInternalServerError, &Response{Code: "internal_error", Message: err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Switch on request method
|
// Switch on request method
|
||||||
switch c.Request.Method {
|
switch c.Request.Method {
|
||||||
case "POST":
|
case "POST":
|
||||||
@ -82,7 +69,7 @@ func MigrateAPI(c *gin.Context) {
|
|||||||
timestamp := startTime.UnixNano() / int64(time.Millisecond)
|
timestamp := startTime.UnixNano() / int64(time.Millisecond)
|
||||||
|
|
||||||
createOptions := cmd.New(timestamp, request.Name, sourceURL.Path)
|
createOptions := cmd.New(timestamp, request.Name, sourceURL.Path)
|
||||||
err = createOptions.SetMetaUp(request.Up)
|
err := createOptions.SetMetaUp(request.Up)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusInternalServerError, &Response{Code: "create_file_error", Message: err.Error()})
|
c.JSON(http.StatusInternalServerError, &Response{Code: "create_file_error", Message: err.Error()})
|
||||||
return
|
return
|
||||||
@ -99,25 +86,23 @@ func MigrateAPI(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
if err != nil {
|
||||||
|
err = createOptions.Delete()
|
||||||
|
if err != nil {
|
||||||
|
logger.Debug(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
// Rescan file system
|
// Rescan file system
|
||||||
err = t.ReScan()
|
err = t.ReScan()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
deleteErr := createOptions.Delete()
|
|
||||||
if deleteErr != nil {
|
|
||||||
c.JSON(http.StatusInternalServerError, &Response{Code: "delete_file_error", Message: deleteErr.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.JSON(http.StatusInternalServerError, &Response{Code: "internal_error", Message: err.Error()})
|
c.JSON(http.StatusInternalServerError, &Response{Code: "internal_error", Message: err.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = t.Migrate(uint64(timestamp), "up"); err != nil {
|
if err = t.Migrate(uint64(timestamp), "up"); err != nil {
|
||||||
deleteErr := createOptions.Delete()
|
|
||||||
if deleteErr != nil {
|
|
||||||
c.JSON(http.StatusInternalServerError, &Response{Code: "delete_file_error", Message: deleteErr.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if strings.HasPrefix(err.Error(), DataAPIError) {
|
if strings.HasPrefix(err.Error(), DataAPIError) {
|
||||||
c.JSON(http.StatusBadRequest, &Response{Code: "data_api_error", Message: strings.TrimPrefix(err.Error(), DataAPIError)})
|
c.JSON(http.StatusBadRequest, &Response{Code: "data_api_error", Message: strings.TrimPrefix(err.Error(), DataAPIError)})
|
||||||
return
|
return
|
||||||
|
@ -2,12 +2,10 @@ package api
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/hasura/graphql-engine/cli/migrate"
|
"github.com/hasura/graphql-engine/cli/migrate"
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type SettingReqeust struct {
|
type SettingReqeust struct {
|
||||||
@ -16,40 +14,13 @@ type SettingReqeust struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func SettingsAPI(c *gin.Context) {
|
func SettingsAPI(c *gin.Context) {
|
||||||
// Get File url
|
// Get migrate instance
|
||||||
sourcePtr, ok := c.Get("filedir")
|
migratePtr, ok := c.Get("migrate")
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
sourceURL := sourcePtr.(*url.URL)
|
t := migratePtr.(*migrate.Migrate)
|
||||||
|
|
||||||
// Get hasuradb url
|
|
||||||
databasePtr, ok := c.Get("dbpath")
|
|
||||||
if !ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert to url.URL
|
|
||||||
databaseURL := databasePtr.(*url.URL)
|
|
||||||
|
|
||||||
// Get Logger
|
|
||||||
loggerPtr, ok := c.Get("logger")
|
|
||||||
if !ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
logger := loggerPtr.(*logrus.Logger)
|
|
||||||
|
|
||||||
// Create new migrate
|
|
||||||
t, err := migrate.New(sourceURL.String(), databaseURL.String(), false, logger)
|
|
||||||
if err != nil {
|
|
||||||
if strings.HasPrefix(err.Error(), DataAPIError) {
|
|
||||||
c.JSON(500, &Response{Code: "data_api_error", Message: err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.JSON(500, &Response{Code: "internal_error", Message: err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Switch on request method
|
// Switch on request method
|
||||||
switch c.Request.Method {
|
switch c.Request.Method {
|
||||||
|
@ -49,6 +49,8 @@ type Driver interface {
|
|||||||
// Migrate will call this function only once per instance.
|
// Migrate will call this function only once per instance.
|
||||||
Close() error
|
Close() error
|
||||||
|
|
||||||
|
Scan() error
|
||||||
|
|
||||||
// Lock should acquire a database lock so that only one migration process
|
// Lock should acquire a database lock so that only one migration process
|
||||||
// can run at a time. Migrate will call this function before Run is called.
|
// can run at a time. Migrate will call this function before Run is called.
|
||||||
// If the implementation can't provide this functionality, return nil.
|
// If the implementation can't provide this functionality, return nil.
|
||||||
|
@ -78,7 +78,7 @@ func WithInstance(config *Config, logger *log.Logger) (database.Driver, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err := hx.getVersions()
|
err := hx.Scan()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -145,6 +145,11 @@ func (h *HasuraDB) Close() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *HasuraDB) Scan() error {
|
||||||
|
h.migrations = database.NewMigrations()
|
||||||
|
return h.getVersions()
|
||||||
|
}
|
||||||
|
|
||||||
func (h *HasuraDB) Lock() error {
|
func (h *HasuraDB) Lock() error {
|
||||||
if h.isLocked {
|
if h.isLocked {
|
||||||
return database.ErrLocked
|
return database.ErrLocked
|
||||||
@ -164,6 +169,10 @@ func (h *HasuraDB) UnLock() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
h.isLocked = false
|
||||||
|
}()
|
||||||
|
|
||||||
if len(h.migrationQuery.Args) == 0 {
|
if len(h.migrationQuery.Args) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -213,7 +222,6 @@ func (h *HasuraDB) UnLock() error {
|
|||||||
}
|
}
|
||||||
return horror.Error(h.config.isCMD)
|
return horror.Error(h.config.isCMD)
|
||||||
}
|
}
|
||||||
h.isLocked = false
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,6 +119,7 @@ func New(sourceUrl string, databaseUrl string, cmd bool, logger *log.Logger) (*M
|
|||||||
if logger == nil {
|
if logger == nil {
|
||||||
logger = log.New()
|
logger = log.New()
|
||||||
}
|
}
|
||||||
|
m.Logger = logger
|
||||||
|
|
||||||
sourceDrv, err := source.Open(sourceUrl, logger)
|
sourceDrv, err := source.Open(sourceUrl, logger)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -150,19 +151,17 @@ func newCommon(cmd bool) *Migrate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *Migrate) ReScan() error {
|
func (m *Migrate) ReScan() error {
|
||||||
sourceDrv, err := source.Open(m.sourceURL, m.Logger)
|
err := m.sourceDrv.Scan()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
m.Logger.Debug(err)
|
m.Logger.Debug(err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
m.sourceDrv = sourceDrv
|
|
||||||
|
|
||||||
databaseDrv, err := database.Open(m.databaseURL, m.isCMD, m.Logger)
|
err = m.databaseDrv.Scan()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
m.Logger.Debug(err)
|
m.Logger.Debug(err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
m.databaseDrv = databaseDrv
|
|
||||||
|
|
||||||
err = m.calculateStatus()
|
err = m.calculateStatus()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -1096,11 +1095,13 @@ func (m *Migrate) unlock() error {
|
|||||||
m.isLockedMu.Lock()
|
m.isLockedMu.Lock()
|
||||||
defer m.isLockedMu.Unlock()
|
defer m.isLockedMu.Unlock()
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
m.isLocked = false
|
||||||
|
}()
|
||||||
|
|
||||||
if err := m.databaseDrv.UnLock(); err != nil {
|
if err := m.databaseDrv.UnLock(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
m.isLocked = false
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,6 +40,8 @@ type Driver interface {
|
|||||||
// Migrate will call this function only once per instance.
|
// Migrate will call this function only once per instance.
|
||||||
Close() error
|
Close() error
|
||||||
|
|
||||||
|
Scan() error
|
||||||
|
|
||||||
// First returns the very first migration version available to the driver.
|
// First returns the very first migration version available to the driver.
|
||||||
// Migrate will call this function multiple times.
|
// Migrate will call this function multiple times.
|
||||||
// If there is no version available, it must return os.ErrNotExist.
|
// If there is no version available, it must return os.ErrNotExist.
|
||||||
|
@ -59,12 +59,6 @@ func (f *File) Open(url string, logger *log.Logger) (source.Driver, error) {
|
|||||||
p = strings.TrimPrefix(p, "/")
|
p = strings.TrimPrefix(p, "/")
|
||||||
}
|
}
|
||||||
|
|
||||||
// scan directory
|
|
||||||
files, err := ioutil.ReadDir(p)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
nf := &File{
|
nf := &File{
|
||||||
url: url,
|
url: url,
|
||||||
logger: logger,
|
logger: logger,
|
||||||
@ -72,24 +66,9 @@ func (f *File) Open(url string, logger *log.Logger) (source.Driver, error) {
|
|||||||
migrations: source.NewMigrations(),
|
migrations: source.NewMigrations(),
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, fi := range files {
|
err = nf.Scan()
|
||||||
if !fi.IsDir() {
|
if err != nil {
|
||||||
m, err := source.DefaultParse(fi.Name(), p)
|
return nil, err
|
||||||
if err != nil {
|
|
||||||
continue // ignore files that we can't parse
|
|
||||||
}
|
|
||||||
ok, err := source.IsEmptyFile(m, p)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if !ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
err = nf.migrations.Append(m)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return nf, nil
|
return nf, nil
|
||||||
}
|
}
|
||||||
@ -99,6 +78,35 @@ func (f *File) Close() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *File) Scan() error {
|
||||||
|
f.migrations = source.NewMigrations()
|
||||||
|
files, err := ioutil.ReadDir(f.path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, fi := range files {
|
||||||
|
if !fi.IsDir() {
|
||||||
|
m, err := source.DefaultParse(fi.Name(), f.path)
|
||||||
|
if err != nil {
|
||||||
|
continue // ignore files that we can't parse
|
||||||
|
}
|
||||||
|
ok, err := source.IsEmptyFile(m, f.path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
err = f.migrations.Append(m)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (f *File) First() (version uint64, err error) {
|
func (f *File) First() (version uint64, err error) {
|
||||||
if v, ok := f.migrations.First(); !ok {
|
if v, ok := f.migrations.First(); !ok {
|
||||||
return 0, &os.PathError{Op: "first", Path: f.path, Err: os.ErrNotExist}
|
return 0, &os.PathError{Op: "first", Path: f.path, Err: os.ErrNotExist}
|
||||||
|
@ -41,6 +41,10 @@ func (s *Stub) Close() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Stub) Scan() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Stub) First() (version uint64, err error) {
|
func (s *Stub) First() (version uint64, err error) {
|
||||||
if v, ok := s.Migrations.First(); !ok {
|
if v, ok := s.Migrations.First(); !ok {
|
||||||
return 0, &os.PathError{Op: "first", Path: s.Url, Err: os.ErrNotExist} // TODO: s.Url can be empty when called with WithInstance
|
return 0, &os.PathError{Op: "first", Path: s.Url, Err: os.ErrNotExist} // TODO: s.Url can be empty when called with WithInstance
|
||||||
|
Loading…
Reference in New Issue
Block a user