Add multi-disk copy workflow

This commit is contained in:
2026-04-23 22:24:32 +03:00
parent 5b3cb9e393
commit 31bac2b5d8
10 changed files with 468 additions and 204 deletions

View File

@@ -34,59 +34,74 @@ func main() {
taskStore := task.NewStore()
cp := copier.New(taskStore)
var activeDB *db.DB
var activeDiskID string
activeDBs := make(map[string]*db.DB)
mountToDiskID := make(map[string]string)
openDiskDB := func(info disk.DiskInfo) {
if activeDiskID == info.DiskID {
return // already open for this disk
if info.DiskID == "" {
return
}
if activeDB != nil {
activeDB.Close()
activeDB = nil
activeDiskID = ""
if prevDiskID, ok := mountToDiskID[info.MountPath]; ok && prevDiskID != info.DiskID {
if prevDB := activeDBs[prevDiskID]; prevDB != nil {
prevDB.Close()
delete(activeDBs, prevDiskID)
cp.SetDB(prevDiskID, nil)
}
}
mountToDiskID[info.MountPath] = info.DiskID
if _, ok := activeDBs[info.DiskID]; ok {
return
}
d, err := db.Open(disk.DBPath(info.MountPath))
if err != nil {
log.Printf("open disk DB: %v", err)
return
}
activeDB = d
activeDiskID = info.DiskID
cp.SetDB(d)
activeDBs[info.DiskID] = d
cp.SetDB(info.DiskID, d)
log.Printf("disk DB opened for %s", info.DiskID)
}
closeDiskDB := func() {
if activeDB != nil {
activeDB.Close()
activeDB = nil
activeDiskID = ""
cp.SetDB(nil)
log.Println("disk DB closed")
closeDiskDB := func(info disk.DiskInfo) {
diskID := info.DiskID
if diskID == "" {
diskID = mountToDiskID[info.MountPath]
}
if diskID == "" {
return
}
cp.Cancel(diskID)
cp.SetDB(diskID, nil)
if d := activeDBs[diskID]; d != nil {
d.Close()
delete(activeDBs, diskID)
log.Printf("disk DB closed for %s", diskID)
}
delete(mountToDiskID, info.MountPath)
}
watcherReady := false
w := watcher.New(*mountPath, 5*time.Second, func(ev watcher.DiskEvent) {
log.Printf("disk: %s -> %s", ev.Prev, ev.Info.State)
log.Printf("disk: %s %s -> %s", ev.Info.MountPath, ev.Prev.State, ev.Info.State)
switch ev.Info.State {
case disk.DiskKnown:
openDiskDB(ev.Info)
if ev.Prev != disk.DiskKnown && cfg.AutoCopy {
if watcherReady && ev.Prev.State != disk.DiskKnown && cfg.AutoCopy {
triggerAutoCopy(cp, cfg, ev.Info, *mediaPath)
}
case disk.DiskForeign:
closeDiskDB(ev.Prev)
case disk.DiskAbsent:
closeDiskDB()
closeDiskDB(ev.Prev)
}
})
// Open DB immediately if disk already connected at startup
{
info, _ := disk.Probe(*mountPath)
if info.State == disk.DiskKnown {
openDiskDB(info)
}
}
w.ProbeNow()
watcherReady = true
srv, err := api.New(api.Deps{
Config: cfg,
@@ -96,6 +111,13 @@ func main() {
Tasks: taskStore,
MediaPath: *mediaPath,
MountPath: *mountPath,
OnDiskInit: func(mountPath, diskID string) {
openDiskDB(disk.DiskInfo{
State: disk.DiskKnown,
DiskID: diskID,
MountPath: mountPath,
})
},
})
if err != nil {
log.Fatalf("init server: %v", err)
@@ -119,7 +141,9 @@ func main() {
shutCtx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
httpSrv.Shutdown(shutCtx)
closeDiskDB()
for _, info := range w.ListDisks() {
closeDiskDB(info)
}
}
func triggerAutoCopy(cp *copier.Copier, cfg *config.Config, info disk.DiskInfo, mediaPath string) {