feat: add user-scoped WebSocket broadcasting for scan progress
- Add UserID field to Job struct for tracking job ownership - Broadcast scan progress updates to user's WebSocket connections - Send real-time updates during scanning (progress, files scanned, new items, errors) This allows the frontend to display live scan progress without HTTP polling. Scanner now associates scan jobs with requesting user for targeted updates.
This commit is contained in:
@@ -86,8 +86,9 @@ func (h *Handler) ScanLibrary(c echo.Context) error {
|
||||
jobID := uuid.New().String()
|
||||
|
||||
job := &services.Job{
|
||||
ID: jobID,
|
||||
Type: services.JobTypeScan,
|
||||
ID: jobID,
|
||||
Type: services.JobTypeScan,
|
||||
UserID: userID,
|
||||
Params: map[string]interface{}{
|
||||
"library_id": req.LibraryID,
|
||||
"folders": folderPaths,
|
||||
|
||||
@@ -2,6 +2,7 @@ package services
|
||||
|
||||
import (
|
||||
"bookhoard/internal/database"
|
||||
wsync "bookhoard/internal/sync"
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
@@ -53,6 +54,7 @@ func (w *Worker) Enqueue(job *Job) {
|
||||
type Job struct {
|
||||
ID string
|
||||
Type JobType
|
||||
UserID string
|
||||
Params map[string]interface{}
|
||||
Status JobStatus
|
||||
CreatedAt time.Time
|
||||
@@ -84,6 +86,7 @@ type JobResult struct {
|
||||
type Worker struct {
|
||||
jobQueue chan *Job
|
||||
results map[string]*JobResult
|
||||
connManager *wsync.ConnectionManager
|
||||
mu sync.RWMutex
|
||||
wg sync.WaitGroup
|
||||
ctx context.Context
|
||||
@@ -91,7 +94,7 @@ type Worker struct {
|
||||
shuttingDown atomic.Bool
|
||||
}
|
||||
|
||||
func NewWorker(numWorkers int) *Worker {
|
||||
func NewWorker(numWorkers int, connManager *wsync.ConnectionManager) *Worker {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
|
||||
w := &Worker{
|
||||
@@ -106,6 +109,8 @@ func NewWorker(numWorkers int) *Worker {
|
||||
go w.worker()
|
||||
}
|
||||
|
||||
w.connManager = connManager
|
||||
|
||||
return w
|
||||
}
|
||||
|
||||
@@ -249,6 +254,21 @@ func (w *Worker) processScanJob(job *Job) (interface{}, error) {
|
||||
result.NewItems = newItems
|
||||
result.Errors = errors
|
||||
}
|
||||
// Broadcast via WebSocket to user
|
||||
if w.connManager != nil && job.UserID != "" {
|
||||
msg := wsync.BroadcastMessage{
|
||||
Type: wsync.MessageTypeScanProgress,
|
||||
Data: map[string]interface{}{
|
||||
"job_id": job.ID,
|
||||
"progress": progress,
|
||||
"files_scanned": filesScanned,
|
||||
"new_items": newItems,
|
||||
"errors": errors,
|
||||
},
|
||||
}
|
||||
|
||||
w.connManager.BroadcastToUser(job.UserID, msg)
|
||||
}
|
||||
}
|
||||
|
||||
if err := scanner.SetFolders(folders); err != nil {
|
||||
|
||||
Reference in New Issue
Block a user