fix: show first progress update immediately instead of waiting for 5%

- Always show the first nonzero progress update so users don't see 0% for
  extended periods on slow downloads or fragment-based downloads
- Keep 5% throttle for subsequent updates to avoid excessive API calls
- Add readProgress summary logging (lines, matches, stderr length)
- Fix progressKeyboard not being updated until progress >= 5%
This commit is contained in:
2026-06-25 16:23:07 +03:30
parent cd7aaeebc2
commit e8120b9529
2 changed files with 23 additions and 10 deletions

View File

@@ -3,6 +3,7 @@ package dl
import ( import (
"bufio" "bufio"
"io" "io"
"log/slog"
"regexp" "regexp"
"strconv" "strconv"
"strings" "strings"
@@ -60,8 +61,11 @@ func parseProgressLine(line string) *progressUpdate {
func readProgress(stderr io.ReadCloser, updates chan<- *domain.DownloadJob, job *domain.DownloadJob) { func readProgress(stderr io.ReadCloser, updates chan<- *domain.DownloadJob, job *domain.DownloadJob) {
var stderrBuf strings.Builder var stderrBuf strings.Builder
scanner := bufio.NewScanner(stderr) scanner := bufio.NewScanner(stderr)
lineCount := 0
matchCount := 0
for scanner.Scan() { for scanner.Scan() {
line := scanner.Text() line := scanner.Text()
lineCount++
if stderrBuf.Len() < 4096 { if stderrBuf.Len() < 4096 {
stderrBuf.WriteString(line) stderrBuf.WriteString(line)
@@ -72,10 +76,12 @@ func readProgress(stderr io.ReadCloser, updates chan<- *domain.DownloadJob, job
if parsed == nil { if parsed == nil {
continue continue
} }
matchCount++
job.Progress = parsed.pct job.Progress = parsed.pct
job.Speed = parsed.speed job.Speed = parsed.speed
job.ETA = parsed.eta job.ETA = parsed.eta
updates <- job updates <- job
} }
job.StderrLog = stderrBuf.String() job.StderrLog = stderrBuf.String()
slog.Info("readProgress finished", "url", job.URL, "lines", lineCount, "matches", matchCount, "stderr_len", len(job.StderrLog))
} }

View File

@@ -396,6 +396,8 @@ func (h *Handler) runDownload(ctx context.Context, job *domain.DownloadJob) {
lastProgress := 0.0 lastProgress := 0.0
for upd := range updates { for upd := range updates {
slog.Info("progress update", "pct", upd.Progress, "speed", upd.Speed, "status", upd.Status)
h.mu.Lock() h.mu.Lock()
currentJob := h.activeJobs[job.UserID] currentJob := h.activeJobs[job.UserID]
h.mu.Unlock() h.mu.Unlock()
@@ -419,8 +421,14 @@ func (h *Handler) runDownload(ctx context.Context, job *domain.DownloadJob) {
return return
} }
if upd.Progress-lastProgress >= domain.ProgressThreshold || upd.Status == domain.StatusCompleted { // Always show the first real progress update, then throttle at 5% intervals
if upd.Progress > 0 && lastProgress == 0 {
lastProgress = upd.Progress lastProgress = upd.Progress
} else if upd.Progress-lastProgress < domain.ProgressThreshold && upd.Status != domain.StatusCompleted {
continue
} else {
lastProgress = upd.Progress
}
if upd.Progress > domain.QuotaProgressThreshold && !job.QuotaApplied && job.FileSize > 0 { if upd.Progress > domain.QuotaProgressThreshold && !job.QuotaApplied && job.FileSize > 0 {
job.QuotaApplied = true job.QuotaApplied = true
@@ -431,7 +439,6 @@ func (h *Handler) runDownload(ctx context.Context, job *domain.DownloadJob) {
text := fmt.Sprintf("Downloading: %s", job.Title) text := fmt.Sprintf("Downloading: %s", job.Title)
h.editText(ctx, job.ChatID, job.MessageID, text, &kb) h.editText(ctx, job.ChatID, job.MessageID, text, &kb)
} }
}
h.mu.Lock() h.mu.Lock()
delete(h.activeJobs, job.UserID) delete(h.activeJobs, job.UserID)