fix(daemon): reportar fallos de arranque de sesión a la web + scan en sesión única
- nuevo agentClient.ReportSessionError → POST /agent/session-error; failSession() en todos los abortos del handler de sesiones (path muerto, ffmpeg ausente, remux, provider debrid, StartHLSSession). Antes eran returns mudos y el player quedaba en "Preparando sesión" hasta agotar el deadline de probes - resolvePlayableFile() unifica la resolución de paths del /stream raw y de las sesiones HLS/remux/direct (remap de base path + stat con retries NFS + directorio→vídeo, antes duplicada y divergente) y distingue file_missing (la web self-heala filas stale) de path_rejected (el fichero existe fuera de los roots = config; la web no debe podar nada) - library.SyncBatches: el batching del sync de biblioteca vive en un solo sitio; el scan manual y el auto-scan sincronizan todos los roots en UNA sesión con scanRoots/fullCycle, en vez de una sesión por root que dejaba al server podar filas de roots que la sesión nunca visitó
This commit is contained in:
parent
4bdd161e02
commit
0dca296fec
6 changed files with 397 additions and 174 deletions
|
|
@ -1,12 +1,74 @@
|
|||
package library
|
||||
|
||||
import (
|
||||
"context"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/torrentclaw/unarr/internal/agent"
|
||||
)
|
||||
|
||||
// SyncOptions describes ONE library sync session — a set of batches sharing a
|
||||
// single syncStartedAt so the server can reap rows not seen by the session.
|
||||
type SyncOptions struct {
|
||||
AgentID string
|
||||
// ScanPath is the primary root, kept for pre-scanRoots servers.
|
||||
ScanPath string
|
||||
// ScanRoots lists every root this session covers (see LibrarySyncRequest).
|
||||
ScanRoots []string
|
||||
// FullCycle: the session spans every configured root — the server may reap
|
||||
// unseen rows regardless of path prefix. NEVER set it for a subtree scan.
|
||||
FullCycle bool
|
||||
// OnProgress, when non-nil, is called after each batch with (sent, total).
|
||||
OnProgress func(sent, total int)
|
||||
}
|
||||
|
||||
// SyncResult aggregates the per-batch server responses of a session.
|
||||
type SyncResult struct {
|
||||
Synced int
|
||||
Matched int
|
||||
Removed int
|
||||
}
|
||||
|
||||
// SyncBatches uploads items to the server in batches of 100 as ONE sync
|
||||
// session: every batch shares the same syncStartedAt and only the final one
|
||||
// carries isLastBatch, so the server's stale-row cleanup sees the whole cycle
|
||||
// at once. The single source of the batching protocol — shared by `unarr scan`
|
||||
// (cmd/scan.go) and the daemon auto-scan (cmd/daemon.go); before this each
|
||||
// root synced as its own session and the per-agent cleanup could reap rows of
|
||||
// roots the session never visited.
|
||||
func SyncBatches(ctx context.Context, ac *agent.Client, items []agent.LibrarySyncItem, opts SyncOptions) (SyncResult, error) {
|
||||
const batchSize = 100
|
||||
var res SyncResult
|
||||
syncStartedAt := time.Now().UTC().Format(time.RFC3339)
|
||||
for i := 0; i < len(items); i += batchSize {
|
||||
end := i + batchSize
|
||||
if end > len(items) {
|
||||
end = len(items)
|
||||
}
|
||||
resp, err := ac.SyncLibrary(ctx, agent.LibrarySyncRequest{
|
||||
Items: items[i:end],
|
||||
ScanPath: opts.ScanPath,
|
||||
AgentID: opts.AgentID,
|
||||
IsLastBatch: end >= len(items),
|
||||
SyncStartedAt: syncStartedAt,
|
||||
ScanRoots: opts.ScanRoots,
|
||||
FullCycle: opts.FullCycle,
|
||||
})
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
res.Synced += resp.Synced
|
||||
res.Matched += resp.Matched
|
||||
res.Removed += resp.Removed
|
||||
if opts.OnProgress != nil {
|
||||
opts.OnProgress(end, len(items))
|
||||
}
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// relToRoot returns the file's path relative to the scan root (forward-slashed),
|
||||
// or "" when it doesn't live under root. The server stores this so streaming can
|
||||
// later reconstruct the absolute path from the agent's *current* root.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue