[#2551] auto register the initial generated snapshot migration to prevent incorrectly reapplying the snapshot on container restart

This commit is contained in:
Gani Georgiev 2023-05-24 09:17:17 +03:00
parent 231ddc9791
commit 6b16b7856b
4 changed files with 67 additions and 17 deletions

View File

@ -4,6 +4,8 @@
- Changed file field to not use `dataTransfer.effectAllowed` when dropping files since it is not reliable and consistent across different OS and browsers ([#2541](https://github.com/pocketbase/pocketbase/issues/2541)).
- Auto register the initial generated snapshot migration to prevent incorrectly reapplying the snapshot on container restart ([#2551](https://github.com/pocketbase/pocketbase/discussions/2551)).
## v0.16.1

View File

@ -23,6 +23,7 @@ import (
"time"
"github.com/AlecAivazis/survey/v2"
"github.com/pocketbase/dbx"
"github.com/pocketbase/pocketbase/core"
"github.com/pocketbase/pocketbase/migrations"
"github.com/pocketbase/pocketbase/models"
@ -102,7 +103,19 @@ func Register(app core.App, rootCmd *cobra.Command, options *Options) error {
// migrations but there is already at least 1 collection created,
// to ensure that the automigrate will work with up-to-date collections data
if !p.hasCustomMigrations() && len(cachedCollections) > 1 {
p.migrateCollectionsHandler(nil, false)
snapshotFile, err := p.migrateCollectionsHandler(nil, false)
if err != nil {
return err
}
// insert the snapshot migration entry
_, insertErr := p.app.Dao().NonconcurrentDB().Insert(migrate.DefaultMigrationsTable, dbx.Params{
"file": snapshotFile,
"applied": time.Now().Unix(),
}).Execute()
if insertErr != nil {
return insertErr
}
}
return nil
@ -141,11 +154,11 @@ func (p *plugin) createCommand() *cobra.Command {
switch cmd {
case "create":
if err := p.migrateCreateHandler("", args[1:], true); err != nil {
if _, err := p.migrateCreateHandler("", args[1:], true); err != nil {
return err
}
case "collections":
if err := p.migrateCollectionsHandler(args[1:], true); err != nil {
if _, err := p.migrateCollectionsHandler(args[1:], true); err != nil {
return err
}
default:
@ -166,18 +179,17 @@ func (p *plugin) createCommand() *cobra.Command {
return command
}
func (p *plugin) migrateCreateHandler(template string, args []string, interactive bool) error {
func (p *plugin) migrateCreateHandler(template string, args []string, interactive bool) (string, error) {
if len(args) < 1 {
return fmt.Errorf("Missing migration file name")
return "", fmt.Errorf("Missing migration file name")
}
name := args[0]
dir := p.options.Dir
resultFilePath := path.Join(
dir,
fmt.Sprintf("%d_%s.%s", time.Now().Unix(), inflector.Snakecase(name), p.options.TemplateLang),
)
filename := fmt.Sprintf("%d_%s.%s", time.Now().Unix(), inflector.Snakecase(name), p.options.TemplateLang)
resultFilePath := path.Join(dir, filename)
if interactive {
confirm := false
@ -187,7 +199,7 @@ func (p *plugin) migrateCreateHandler(template string, args []string, interactiv
survey.AskOne(prompt, &confirm)
if !confirm {
fmt.Println("The command has been cancelled")
return nil
return "", nil
}
}
@ -200,34 +212,34 @@ func (p *plugin) migrateCreateHandler(template string, args []string, interactiv
template, templateErr = p.goBlankTemplate()
}
if templateErr != nil {
return fmt.Errorf("Failed to resolve create template: %v\n", templateErr)
return "", fmt.Errorf("Failed to resolve create template: %v\n", templateErr)
}
}
// ensure that the migrations dir exist
if err := os.MkdirAll(dir, os.ModePerm); err != nil {
return err
return "", err
}
// save the migration file
if err := os.WriteFile(resultFilePath, []byte(template), 0644); err != nil {
return fmt.Errorf("Failed to save migration file %q: %v\n", resultFilePath, err)
return "", fmt.Errorf("Failed to save migration file %q: %v\n", resultFilePath, err)
}
if interactive {
fmt.Printf("Successfully created file %q\n", resultFilePath)
}
return nil
return filename, nil
}
func (p *plugin) migrateCollectionsHandler(args []string, interactive bool) error {
func (p *plugin) migrateCollectionsHandler(args []string, interactive bool) (string, error) {
createArgs := []string{"collections_snapshot"}
createArgs = append(createArgs, args...)
collections := []*models.Collection{}
if err := p.app.Dao().CollectionQuery().OrderBy("created ASC").All(&collections); err != nil {
return fmt.Errorf("Failed to fetch migrations list: %v", err)
return "", fmt.Errorf("Failed to fetch migrations list: %v", err)
}
var template string
@ -238,7 +250,7 @@ func (p *plugin) migrateCollectionsHandler(args []string, interactive bool) erro
template, templateErr = p.goSnapshotTemplate(collections)
}
if templateErr != nil {
return fmt.Errorf("Failed to resolve template: %v", templateErr)
return "", fmt.Errorf("Failed to resolve template: %v", templateErr)
}
return p.migrateCreateHandler(template, createArgs, interactive)

View File

@ -6,11 +6,14 @@ import (
"strings"
"testing"
"github.com/pocketbase/dbx"
"github.com/pocketbase/pocketbase/core"
"github.com/pocketbase/pocketbase/daos"
"github.com/pocketbase/pocketbase/models"
"github.com/pocketbase/pocketbase/models/schema"
"github.com/pocketbase/pocketbase/plugins/migratecmd"
"github.com/pocketbase/pocketbase/tests"
"github.com/pocketbase/pocketbase/tools/migrate"
"github.com/pocketbase/pocketbase/tools/types"
)
@ -776,3 +779,36 @@ func TestAutomigrateCollectionNoChanges(t *testing.T) {
}
}
}
func TestInitialAutoSnapshot(t *testing.T) {
app, _ := tests.NewTestApp()
defer app.Cleanup()
migrationsDir := filepath.Join(app.DataDir(), "_test_auto_snapshot_")
migratecmd.MustRegister(app, nil, &migratecmd.Options{
TemplateLang: migratecmd.TemplateLangJS,
Automigrate: true,
Dir: migrationsDir,
})
app.Bootstrap()
app.OnBeforeServe().Trigger(&core.ServeEvent{
App: app,
})
var foundFiles []string
err := app.Dao().NonconcurrentDB().Select("file").
From(migrate.DefaultMigrationsTable).
Where(dbx.NewExp("file like '%collections_snapshot.js'")).
Column(&foundFiles)
if err != nil {
t.Fatal(err)
}
if len(foundFiles) != 1 {
t.Fatalf("Expected 1 collections_snapshot migration, found %v", foundFiles)
}
}

Binary file not shown.