[#6972] wrapped backup restore in a transaction as an extra precaution

This commit is contained in:
Gani Georgiev 2025-06-26 22:15:03 +03:00
parent 2c6f99418f
commit 51bc9f3982
2 changed files with 33 additions and 17 deletions

View File

@ -2,6 +2,8 @@
- Added the triggered rate rimit rule in the error log `details`. - Added the triggered rate rimit rule in the error log `details`.
- Other minor improvements (wrapped the backup restore in a transaction as an extra precaution, updated npm deps, regenerated JSVM docs with the recent tygoja changes, etc.).
## v0.28.4 ## v0.28.4

View File

@ -228,7 +228,7 @@ func (app *BaseApp) RestoreBackup(ctx context.Context, name string) error {
} else { } else {
// manually construct the local path to avoid creating a copy of the zip file // manually construct the local path to avoid creating a copy of the zip file
// since the blob reader currently doesn't implement ReaderAt // since the blob reader currently doesn't implement ReaderAt
zipPath := filepath.Join(app.DataDir(), LocalBackupsDirName, filepath.Base(name)) zipPath := filepath.Join(e.App.DataDir(), LocalBackupsDirName, filepath.Base(name))
err = archive.Extract(zipPath, extractedDataDir) err = archive.Extract(zipPath, extractedDataDir)
if err != nil { if err != nil {
@ -242,29 +242,43 @@ func (app *BaseApp) RestoreBackup(ctx context.Context, name string) error {
return fmt.Errorf("data.db file is missing or invalid: %w", err) return fmt.Errorf("data.db file is missing or invalid: %w", err)
} }
// move the current pb_data content to a special temp location
// that will hold the old data between dirs replace
// (the temp dir will be automatically removed on the next app start)
oldTempDataDir := filepath.Join(localTempDir, "old_pb_data_"+security.PseudorandomString(8)) oldTempDataDir := filepath.Join(localTempDir, "old_pb_data_"+security.PseudorandomString(8))
if err := osutils.MoveDirContent(e.App.DataDir(), oldTempDataDir, e.Exclude...); err != nil {
return fmt.Errorf("failed to move the current pb_data content to a temp location: %w", err)
}
// move the extracted archive content to the app's pb_data replaceErr := e.App.RunInTransaction(func(txApp App) error {
if err := osutils.MoveDirContent(extractedDataDir, e.App.DataDir(), e.Exclude...); err != nil { return txApp.AuxRunInTransaction(func(txApp App) error {
return fmt.Errorf("failed to move the extracted archive content to pb_data: %w", err) // move the current pb_data content to a special temp location
// that will hold the old data between dirs replace
// (the temp dir will be automatically removed on the next app start)
if err := osutils.MoveDirContent(txApp.DataDir(), oldTempDataDir, e.Exclude...); err != nil {
return fmt.Errorf("failed to move the current pb_data content to a temp location: %w", err)
}
// move the extracted archive content to the app's pb_data
if err := osutils.MoveDirContent(extractedDataDir, txApp.DataDir(), e.Exclude...); err != nil {
return fmt.Errorf("failed to move the extracted archive content to pb_data: %w", err)
}
return nil
})
})
if replaceErr != nil {
return replaceErr
} }
revertDataDirChanges := func() error { revertDataDirChanges := func() error {
if err := osutils.MoveDirContent(e.App.DataDir(), extractedDataDir, e.Exclude...); err != nil { return e.App.RunInTransaction(func(txApp App) error {
return fmt.Errorf("failed to revert the extracted dir change: %w", err) return txApp.AuxRunInTransaction(func(txApp App) error {
} if err := osutils.MoveDirContent(txApp.DataDir(), extractedDataDir, e.Exclude...); err != nil {
return fmt.Errorf("failed to revert the extracted dir change: %w", err)
}
if err := osutils.MoveDirContent(oldTempDataDir, e.App.DataDir(), e.Exclude...); err != nil { if err := osutils.MoveDirContent(oldTempDataDir, txApp.DataDir(), e.Exclude...); err != nil {
return fmt.Errorf("failed to revert old pb_data dir change: %w", err) return fmt.Errorf("failed to revert old pb_data dir change: %w", err)
} }
return nil return nil
})
})
} }
// restart the app // restart the app