feat(orchestrator): build copy plan from per-account mapping + exclusions
This commit is contained in:
@@ -16,6 +16,34 @@ import (
|
||||
var ErrNotTested = errors.New("accounts not fully tested")
|
||||
var ErrAlreadyRunning = errors.New("task already running")
|
||||
|
||||
// folderPlan is one source folder scheduled for copy and its destination name.
|
||||
type folderPlan struct {
|
||||
src, dst string
|
||||
total int64
|
||||
}
|
||||
|
||||
// planFolders decides which of an account's source folders to copy and where.
|
||||
// Excluded source folders are dropped; a folder absent from mapping keeps its
|
||||
// own name. Order follows the input folder list.
|
||||
func planFolders(folders []string, mapping map[string]string, excluded []string) []folderPlan {
|
||||
skip := make(map[string]struct{}, len(excluded))
|
||||
for _, e := range excluded {
|
||||
skip[e] = struct{}{}
|
||||
}
|
||||
plan := make([]folderPlan, 0, len(folders))
|
||||
for _, f := range folders {
|
||||
if _, ok := skip[f]; ok {
|
||||
continue
|
||||
}
|
||||
df := f
|
||||
if m, ok := mapping[f]; ok && m != "" {
|
||||
df = m
|
||||
}
|
||||
plan = append(plan, folderPlan{src: f, dst: df})
|
||||
}
|
||||
return plan
|
||||
}
|
||||
|
||||
type Orchestrator struct {
|
||||
store *store.Store
|
||||
hub *wshub.Hub
|
||||
@@ -269,27 +297,19 @@ func (o *Orchestrator) runAccount(ctx context.Context, task store.Task, runID in
|
||||
return o.accountFailed(ctx, task.ID, a, srcEP, dstEP, "src", err)
|
||||
}
|
||||
|
||||
// Planning pass: EXAMINE every folder up front to learn the total message
|
||||
// count, so the UI can show an accurate overall bar / ETA before copying.
|
||||
type folderPlan struct {
|
||||
src, dst string
|
||||
total int64
|
||||
}
|
||||
plan := make([]folderPlan, 0, len(folders))
|
||||
// Planning pass: decide folders from the account's own config, then EXAMINE
|
||||
// each to learn message counts for the overall progress bar.
|
||||
plan := planFolders(folders, a.FolderMapping, a.ExcludedFolders)
|
||||
var grandTotal int64
|
||||
for _, folder := range folders {
|
||||
for i := range plan {
|
||||
if actx.Err() != nil {
|
||||
break
|
||||
}
|
||||
df := folder
|
||||
if m, ok := task.FolderMapping[folder]; ok {
|
||||
df = m
|
||||
}
|
||||
n, cerr := imapx.FolderMessageCount(src, folder)
|
||||
n, cerr := imapx.FolderMessageCount(src, plan[i].src)
|
||||
if cerr != nil && actx.Err() == nil {
|
||||
slog.Warn("count folder failed", "account", a.ID, "folder", folder, "err", cerr)
|
||||
slog.Warn("count folder failed", "account", a.ID, "folder", plan[i].src, "err", cerr)
|
||||
}
|
||||
plan = append(plan, folderPlan{src: folder, dst: df, total: n})
|
||||
plan[i].total = n
|
||||
grandTotal += n
|
||||
}
|
||||
o.hub.Publish(wshub.Event{Type: "plan", TaskID: task.ID, Data: map[string]any{
|
||||
|
||||
Reference in New Issue
Block a user