mirror of
https://github.com/mjl-/mox.git
synced 2025-06-28 05:08:14 +03:00
mox backup: skip message files that were added to queue or account message directories while making the backup, instead of storing them and warning about them
by storing them, a restore may need the -fix flag to become usable again. it makes more sense to just skip these files. they are not part of the consistent snapshot.
This commit is contained in:
parent
76e96ee673
commit
890c75367a
39
backup.go
39
backup.go
@ -11,6 +11,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
@ -413,13 +414,16 @@ func backupctl(ctx context.Context, ctl *ctl) {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// Link/copy known message files. Warn if files are missing or unexpected
|
// Link/copy known message files. If a message has been removed while we read the
|
||||||
// (though a message file could have been removed just now due to delivery, or a
|
// database, our backup is not consistent and the backup will be marked failed.
|
||||||
// new message may have been queued).
|
|
||||||
tmMsgs := time.Now()
|
tmMsgs := time.Now()
|
||||||
seen := map[string]struct{}{}
|
seen := map[string]struct{}{}
|
||||||
var nlinked, ncopied int
|
var nlinked, ncopied int
|
||||||
|
var maxID int64
|
||||||
err = bstore.QueryDB[queue.Msg](ctx, db).ForEach(func(m queue.Msg) error {
|
err = bstore.QueryDB[queue.Msg](ctx, db).ForEach(func(m queue.Msg) error {
|
||||||
|
if m.ID > maxID {
|
||||||
|
maxID = m.ID
|
||||||
|
}
|
||||||
mp := store.MessagePath(m.ID)
|
mp := store.MessagePath(m.ID)
|
||||||
seen[mp] = struct{}{}
|
seen[mp] = struct{}{}
|
||||||
srcpath := filepath.Join(srcDataDir, "queue", mp)
|
srcpath := filepath.Join(srcDataDir, "queue", mp)
|
||||||
@ -442,7 +446,9 @@ func backupctl(ctx context.Context, ctl *ctl) {
|
|||||||
slog.Duration("duration", time.Since(tmMsgs)))
|
slog.Duration("duration", time.Since(tmMsgs)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read through all files in queue directory and warn about anything we haven't handled yet.
|
// Read through all files in queue directory and warn about anything we haven't
|
||||||
|
// handled yet. Message files that are newer than we expect from our consistent
|
||||||
|
// database snapshot are ignored.
|
||||||
tmWalk := time.Now()
|
tmWalk := time.Now()
|
||||||
srcqdir := filepath.Join(srcDataDir, "queue")
|
srcqdir := filepath.Join(srcDataDir, "queue")
|
||||||
err = filepath.WalkDir(srcqdir, func(srcqpath string, d fs.DirEntry, err error) error {
|
err = filepath.WalkDir(srcqdir, func(srcqpath string, d fs.DirEntry, err error) error {
|
||||||
@ -460,6 +466,12 @@ func backupctl(ctx context.Context, ctl *ctl) {
|
|||||||
if p == "index.db" {
|
if p == "index.db" {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
// Skip any messages that were added since we started on our consistent snapshot.
|
||||||
|
// We don't want to cause spurious backup warnings.
|
||||||
|
if id, err := strconv.ParseInt(filepath.Base(p), 10, 64); err == nil && maxID > 0 && id > maxID && p == store.MessagePath(id) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
qp := filepath.Join("queue", p)
|
qp := filepath.Join("queue", p)
|
||||||
xwarnx("backing up unrecognized file in queue directory", nil, slog.String("path", qp))
|
xwarnx("backing up unrecognized file in queue directory", nil, slog.String("path", qp))
|
||||||
backupFile(qp)
|
backupFile(qp)
|
||||||
@ -520,13 +532,16 @@ func backupctl(ctx context.Context, ctl *ctl) {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// Link/copy known message files. Warn if files are missing or unexpected (though a
|
// Link/copy known message files. If a message has been removed while we read the
|
||||||
// message file could have been added just now due to delivery, or a message have
|
// database, our backup is not consistent and the backup will be marked failed.
|
||||||
// been removed).
|
|
||||||
tmMsgs := time.Now()
|
tmMsgs := time.Now()
|
||||||
seen := map[string]struct{}{}
|
seen := map[string]struct{}{}
|
||||||
|
var maxID int64
|
||||||
var nlinked, ncopied int
|
var nlinked, ncopied int
|
||||||
err = bstore.QueryDB[store.Message](ctx, db).FilterEqual("Expunged", false).ForEach(func(m store.Message) error {
|
err = bstore.QueryDB[store.Message](ctx, db).FilterEqual("Expunged", false).ForEach(func(m store.Message) error {
|
||||||
|
if m.ID > maxID {
|
||||||
|
maxID = m.ID
|
||||||
|
}
|
||||||
mp := store.MessagePath(m.ID)
|
mp := store.MessagePath(m.ID)
|
||||||
seen[mp] = struct{}{}
|
seen[mp] = struct{}{}
|
||||||
amp := filepath.Join("accounts", acc.Name, "msg", mp)
|
amp := filepath.Join("accounts", acc.Name, "msg", mp)
|
||||||
@ -550,7 +565,9 @@ func backupctl(ctx context.Context, ctl *ctl) {
|
|||||||
slog.Duration("duration", time.Since(tmMsgs)))
|
slog.Duration("duration", time.Since(tmMsgs)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read through all files in account directory and warn about anything we haven't handled yet.
|
// Read through all files in queue directory and warn about anything we haven't
|
||||||
|
// handled yet. Message files that are newer than we expect from our consistent
|
||||||
|
// database snapshot are ignored.
|
||||||
tmWalk := time.Now()
|
tmWalk := time.Now()
|
||||||
srcadir := filepath.Join(srcDataDir, "accounts", acc.Name)
|
srcadir := filepath.Join(srcDataDir, "accounts", acc.Name)
|
||||||
err = filepath.WalkDir(srcadir, func(srcapath string, d fs.DirEntry, err error) error {
|
err = filepath.WalkDir(srcadir, func(srcapath string, d fs.DirEntry, err error) error {
|
||||||
@ -568,6 +585,12 @@ func backupctl(ctx context.Context, ctl *ctl) {
|
|||||||
if _, ok := seen[mp]; ok {
|
if _, ok := seen[mp]; ok {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Skip any messages that were added since we started on our consistent snapshot.
|
||||||
|
// We don't want to cause spurious backup warnings.
|
||||||
|
if id, err := strconv.ParseInt(l[len(l)-1], 10, 64); err == nil && id > maxID && mp == store.MessagePath(id) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
switch p {
|
switch p {
|
||||||
case "index.db", "junkfilter.db", "junkfilter.bloom":
|
case "index.db", "junkfilter.db", "junkfilter.bloom":
|
||||||
|
Loading…
x
Reference in New Issue
Block a user