Fix SSE timeout issues with long-running stream discovery

Problem:
- WriteTimeout was 30 seconds
- Progress only sent when values changed
- Long ffprobe tests (7-8s each) could cause 30+ seconds without writes
- Result: "curl: (18) transfer closed with outstanding read data remaining"

Solution:
- Increase WriteTimeout from 30s to 5 minutes
- Send progress every 1 second (instead of 3 seconds)
- Always send progress, even if values unchanged
- Guarantees write every second, preventing timeout

Changes:
- internal/config/config.go: WriteTimeout 30s → 5min
- internal/camera/discovery/scanner.go:
  - Progress ticker 3s → 1s
  - Remove "only if changed" check
  - Always send progress to keep connection alive

Testing:
- HiWatch camera with 591 streams: Previously timed out at ~338/591
- Should now complete all 591 streams without timeout
This commit is contained in:
eduard256
2025-11-22 19:48:03 +03:00
parent 90c4416709
commit a6e9cc2c5e
2 changed files with 8 additions and 14 deletions
+7 -13
View File
@@ -409,26 +409,20 @@ func (s *Scanner) testStreamsConcurrently(ctx context.Context, streams []models.
defer cancelProgress()
go func() {
ticker := time.NewTicker(3 * time.Second)
ticker := time.NewTicker(1 * time.Second)
defer ticker.Stop()
lastTested := int32(0)
for {
select {
case <-progressCtx.Done():
return
case <-ticker.C:
currentTested := atomic.LoadInt32(&tested)
// Only send if there's been progress
if currentTested != lastTested {
_ = streamWriter.SendJSON("progress", models.ProgressMessage{
Tested: int(currentTested),
Found: int(atomic.LoadInt32(&found)),
Remaining: len(streams) - int(currentTested),
})
lastTested = currentTested
}
// Send progress every second to prevent WriteTimeout
_ = streamWriter.SendJSON("progress", models.ProgressMessage{
Tested: int(atomic.LoadInt32(&tested)),
Found: int(atomic.LoadInt32(&found)),
Remaining: len(streams) - int(atomic.LoadInt32(&tested)),
})
}
}
}()
+1 -1
View File
@@ -73,7 +73,7 @@ func Load() *Config {
Server: ServerConfig{
Listen: ":4567", // Default listen address
ReadTimeout: 30 * time.Second,
WriteTimeout: 30 * time.Second,
WriteTimeout: 5 * time.Minute, // Increased for SSE long-polling
},
Database: DatabaseConfig{
DataPath: dataPath,