Files
yellowjacket/backend/library/scan_control.go
T
yonlu cf22e52a64 feat(09-01): add scan control fields and per-scan cancellable context
- Add scanActive, scanCancel, scanPaused, scanPauseCh fields to Library struct
- Create scan_control.go with CancelScan, PauseScan, ResumeScan, IsScanActive, IsScanPaused
- Thread per-scan scanCtx through walk and worker pipeline
- Add waitIfPaused checkpoint before each worker extraction
- Skip orphan cleanup and variant generation on cancelled scan
- Emit LibraryScanCancelled instead of LibraryScanComplete when cancelled
2026-03-06 21:30:49 -05:00

89 lines
1.7 KiB
Go

package library
import (
"context"
"github.com/wailsapp/wails/v2/pkg/runtime"
"yellowjacket/backend/events"
)
// CancelScan cancels an in-progress scan. Returns immediately;
// scan goroutines stop at their next checkpoint.
func (l *Library) CancelScan() {
l.mu.Lock()
cancel := l.scanCancel
l.mu.Unlock()
if cancel != nil {
cancel()
}
}
// PauseScan pauses an in-progress scan. Workers block at their
// next pause checkpoint until ResumeScan is called.
func (l *Library) PauseScan() {
l.mu.Lock()
defer l.mu.Unlock()
if !l.scanActive || l.scanPaused {
return
}
l.scanPaused = true
l.scanPauseCh = make(chan struct{})
runtime.EventsEmit(l.ctx, events.LibraryScanPaused)
}
// ResumeScan unblocks a paused scan.
func (l *Library) ResumeScan() {
l.mu.Lock()
defer l.mu.Unlock()
if !l.scanPaused {
return
}
l.scanPaused = false
close(l.scanPauseCh) // unblocks all waiting workers
runtime.EventsEmit(l.ctx, events.LibraryScanResumed)
}
// IsScanActive returns whether a scan is currently running.
func (l *Library) IsScanActive() bool {
l.mu.Lock()
defer l.mu.Unlock()
return l.scanActive
}
// IsScanPaused returns whether the scan is currently paused.
func (l *Library) IsScanPaused() bool {
l.mu.Lock()
defer l.mu.Unlock()
return l.scanPaused
}
// waitIfPaused blocks the calling goroutine if the scan is paused.
// Returns ctx.Err() if the context is cancelled while waiting.
func (l *Library) waitIfPaused(ctx context.Context) error {
l.mu.Lock()
ch := l.scanPauseCh
paused := l.scanPaused
l.mu.Unlock()
if !paused || ch == nil {
return nil
}
select {
case <-ch: // closed = unpaused
return nil
case <-ctx.Done():
return ctx.Err()
}
}