Add scoped migration acceptance run
This commit is contained in:
parent
253435d87f
commit
813762f43f
3 changed files with 39 additions and 3 deletions
|
|
@ -137,9 +137,13 @@ func (m *imapClientMailbox) listMailboxes() ([]imapListMailbox, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *imapClientMailbox) fetchAll(folder string) ([]RawMessage, error) {
|
func (m *imapClientMailbox) fetchAll(folder string) ([]RawMessage, error) {
|
||||||
if _, err := m.c.Select(folder, &imap.SelectOptions{ReadOnly: true}).Wait(); err != nil {
|
selected, err := m.c.Select(folder, &imap.SelectOptions{ReadOnly: true}).Wait()
|
||||||
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if selected.NumMessages == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
section := &imap.FetchItemBodySection{Peek: true}
|
section := &imap.FetchItemBodySection{Peek: true}
|
||||||
seqSet := imap.SeqSet{}
|
seqSet := imap.SeqSet{}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -22,6 +23,14 @@ import (
|
||||||
// name = Konto-Name oder "all". watch = true -> Delta-Schleife bis Abbruch
|
// name = Konto-Name oder "all". watch = true -> Delta-Schleife bis Abbruch
|
||||||
// (Cutover-Fenster), sonst einmaliger Durchlauf.
|
// (Cutover-Fenster), sonst einmaliger Durchlauf.
|
||||||
func RunMigration(name string, watch bool, interval time.Duration) error {
|
func RunMigration(name string, watch bool, interval time.Duration) error {
|
||||||
|
return runMigration(name, watch, interval, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func RunMigrationFolders(name string, folders []string) error {
|
||||||
|
return runMigration(name, false, 0, selectedFolderSet(folders))
|
||||||
|
}
|
||||||
|
|
||||||
|
func runMigration(name string, watch bool, interval time.Duration, selectedFolders map[string]bool) error {
|
||||||
if interval <= 0 {
|
if interval <= 0 {
|
||||||
interval = 60 * time.Second
|
interval = 60 * time.Second
|
||||||
}
|
}
|
||||||
|
|
@ -45,7 +54,7 @@ func RunMigration(name string, watch bool, interval time.Duration) error {
|
||||||
if !a.Active {
|
if !a.Active {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if err := migrateAccount(a); err != nil {
|
if err := migrateAccount(a, selectedFolders); err != nil {
|
||||||
if !watch {
|
if !watch {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -62,7 +71,7 @@ func RunMigration(name string, watch bool, interval time.Duration) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// migrateAccount fuehrt einen einzelnen Umzug aus (ein Durchlauf).
|
// migrateAccount fuehrt einen einzelnen Umzug aus (ein Durchlauf).
|
||||||
func migrateAccount(a Account) error {
|
func migrateAccount(a Account, selectedFolders map[string]bool) error {
|
||||||
if a.ID == 0 {
|
if a.ID == 0 {
|
||||||
stored, err := GetAccount(a.Name)
|
stored, err := GetAccount(a.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -102,6 +111,9 @@ func migrateAccount(a Account) error {
|
||||||
}
|
}
|
||||||
total, done, errs := 0, 0, 0
|
total, done, errs := 0, 0, 0
|
||||||
for _, folder := range folders {
|
for _, folder := range folders {
|
||||||
|
if len(selectedFolders) > 0 && !selectedFolders[folder.Name] {
|
||||||
|
continue
|
||||||
|
}
|
||||||
dstFolder := MapSourceToTarget(folder.Name, folder.Attrs, folder.Delim, dst.Delim(), targets, "")
|
dstFolder := MapSourceToTarget(folder.Name, folder.Attrs, folder.Delim, dst.Delim(), targets, "")
|
||||||
if dstFolder == "" {
|
if dstFolder == "" {
|
||||||
dstFolder = folder.Name
|
dstFolder = folder.Name
|
||||||
|
|
@ -165,6 +177,17 @@ func migrateAccount(a Account) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func selectedFolderSet(folders []string) map[string]bool {
|
||||||
|
out := make(map[string]bool, len(folders))
|
||||||
|
for _, folder := range folders {
|
||||||
|
folder = strings.TrimSpace(folder)
|
||||||
|
if folder != "" {
|
||||||
|
out[folder] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
func CheckAccount(name string) error {
|
func CheckAccount(name string) error {
|
||||||
a, err := GetAccount(name)
|
a, err := GetAccount(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
9
main.go
9
main.go
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"mail-graveyard/backend"
|
"mail-graveyard/backend"
|
||||||
|
|
@ -17,6 +18,7 @@ var frontend embed.FS
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
runOnce := flag.String("run", "", "einen Umzugs-Job einmalig ausfuehren (Konto-Name oder 'all'), ohne Web-UI")
|
runOnce := flag.String("run", "", "einen Umzugs-Job einmalig ausfuehren (Konto-Name oder 'all'), ohne Web-UI")
|
||||||
|
runFolders := flag.String("folders", "", "optionale kommaseparierte Ordnerliste fuer -run (CLI-Abnahme/Teilumzug)")
|
||||||
watch := flag.Bool("watch", false, "Delta-Sync in Schleife bis Stop (Cutover-Fenster)")
|
watch := flag.Bool("watch", false, "Delta-Sync in Schleife bis Stop (Cutover-Fenster)")
|
||||||
watchInterval := flag.Duration("watch-interval", 60*time.Second, "Pause zwischen Watch-Durchlaeufen")
|
watchInterval := flag.Duration("watch-interval", 60*time.Second, "Pause zwischen Watch-Durchlaeufen")
|
||||||
seedAccount := flag.String("seed-account", "", "Konto aus lokaler JSON-Datei in die DB schreiben (nur CLI/Test)")
|
seedAccount := flag.String("seed-account", "", "Konto aus lokaler JSON-Datei in die DB schreiben (nur CLI/Test)")
|
||||||
|
|
@ -44,6 +46,13 @@ func main() {
|
||||||
|
|
||||||
// CLI-Modus: ohne Web laufen lassen (Cronjob / Cutover).
|
// CLI-Modus: ohne Web laufen lassen (Cronjob / Cutover).
|
||||||
if *runOnce != "" {
|
if *runOnce != "" {
|
||||||
|
if strings.TrimSpace(*runFolders) != "" {
|
||||||
|
if *watch {
|
||||||
|
log.Fatal("-folders kann nicht mit -watch kombiniert werden")
|
||||||
|
}
|
||||||
|
must(backend.RunMigrationFolders(*runOnce, strings.Split(*runFolders, ",")))
|
||||||
|
return
|
||||||
|
}
|
||||||
must(backend.RunMigration(*runOnce, *watch, *watchInterval))
|
must(backend.RunMigration(*runOnce, *watch, *watchInterval))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue