Sync from /srv/compose/unified-media-manager
This commit is contained in:
131
internal/worker/queue.go
Normal file
131
internal/worker/queue.go
Normal file
@@ -0,0 +1,131 @@
|
||||
package worker
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"time"
|
||||
|
||||
"github.com/TopherMayor/unified-media-manager/internal/config"
|
||||
"github.com/TopherMayor/unified-media-manager/internal/db"
|
||||
"github.com/TopherMayor/unified-media-manager/internal/service"
|
||||
)
|
||||
|
||||
type QueueProcessor struct {
|
||||
database *db.DB
|
||||
importSvc *service.ImportService
|
||||
dcSvc *service.DownloadClientService
|
||||
cfg *config.Config
|
||||
activitySvc *service.ActivityService
|
||||
}
|
||||
|
||||
func NewQueueProcessor(database *db.DB, importSvc *service.ImportService, dcSvc *service.DownloadClientService, cfg *config.Config, activitySvc *service.ActivityService) *QueueProcessor {
|
||||
return &QueueProcessor{
|
||||
database: database,
|
||||
importSvc: importSvc,
|
||||
dcSvc: dcSvc,
|
||||
cfg: cfg,
|
||||
activitySvc: activitySvc,
|
||||
}
|
||||
}
|
||||
|
||||
func (w *QueueProcessor) Name() string {
|
||||
return "queue_processor"
|
||||
}
|
||||
|
||||
func (w *QueueProcessor) CronExpr() string {
|
||||
return w.cfg.WorkerQueueInterval
|
||||
}
|
||||
|
||||
func (w *QueueProcessor) Run(ctx context.Context) error {
|
||||
ctx, cancel := context.WithTimeout(ctx, 30*time.Second)
|
||||
defer cancel()
|
||||
|
||||
progressUpdated := 0
|
||||
errors := 0
|
||||
|
||||
nzbClients, err := w.dcSvc.GetAllEnabled(ctx, "nzb")
|
||||
if err != nil {
|
||||
slog.Error("failed to get nzb clients", "error", err)
|
||||
}
|
||||
torrentClients, err := w.dcSvc.GetAllEnabled(ctx, "torrent")
|
||||
if err != nil {
|
||||
slog.Error("failed to get torrent clients", "error", err)
|
||||
}
|
||||
|
||||
allClients := append(nzbClients, torrentClients...)
|
||||
|
||||
for _, client := range allClients {
|
||||
rows, err := w.database.Pool.Query(ctx,
|
||||
`SELECT id, download_id FROM download_queue
|
||||
WHERE status = 'downloading' AND download_client = $1 AND download_id IS NOT NULL AND download_id != ''`,
|
||||
client.Config.Name)
|
||||
if err != nil {
|
||||
slog.Error("failed to query active downloads", "client", client.Config.Name, "error", err)
|
||||
continue
|
||||
}
|
||||
|
||||
type queueItem struct {
|
||||
id int64
|
||||
downloadID string
|
||||
}
|
||||
var items []queueItem
|
||||
for rows.Next() {
|
||||
var item queueItem
|
||||
if err := rows.Scan(&item.id, &item.downloadID); err != nil {
|
||||
slog.Error("failed to scan queue item", "error", err)
|
||||
continue
|
||||
}
|
||||
items = append(items, item)
|
||||
}
|
||||
rows.Close()
|
||||
|
||||
for _, item := range items {
|
||||
progress, err := client.Client.GetProgress(ctx, item.downloadID)
|
||||
if err != nil {
|
||||
slog.Error("failed to get download progress", "id", item.downloadID, "error", err)
|
||||
errors++
|
||||
continue
|
||||
}
|
||||
|
||||
// Detect failed downloads
|
||||
if progress.Status == "failed" || progress.Status == "error" {
|
||||
if w.activitySvc != nil {
|
||||
w.activitySvc.LogAsync(service.LogEntry{
|
||||
EventType: "download_failed",
|
||||
Title: fmt.Sprintf("Download failed: %s", item.downloadID),
|
||||
Data: []byte(fmt.Sprintf(`{"queue_id":%d,"download_id":"%s"}`, item.id, item.downloadID)),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
_, err = w.database.Pool.Exec(ctx,
|
||||
"UPDATE download_queue SET progress = $1, updated_at = NOW() WHERE id = $2",
|
||||
progress.Progress, item.id)
|
||||
if err != nil {
|
||||
slog.Error("failed to update progress", "id", item.id, "error", err)
|
||||
errors++
|
||||
continue
|
||||
}
|
||||
progressUpdated++
|
||||
}
|
||||
}
|
||||
|
||||
report, err := w.importSvc.ProcessCompleted(ctx)
|
||||
if err != nil {
|
||||
slog.Error("failed to process completed downloads", "error", err)
|
||||
errors++
|
||||
}
|
||||
|
||||
imported := 0
|
||||
if report != nil {
|
||||
imported = report.Imported
|
||||
}
|
||||
|
||||
slog.Info("queue processor completed",
|
||||
"progress_updated", progressUpdated,
|
||||
"completed_imported", imported,
|
||||
"errors", errors)
|
||||
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user