From e8120b952985210f7907459fc15a74257f6cffcc Mon Sep 17 00:00:00 2001 From: db123 Date: Thu, 25 Jun 2026 16:23:07 +0330 Subject: [PATCH] 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% --- internal/dl/progress.go | 6 ++++++ internal/handler/download.go | 27 +++++++++++++++++---------- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/internal/dl/progress.go b/internal/dl/progress.go index e37e454..0d9267b 100644 --- a/internal/dl/progress.go +++ b/internal/dl/progress.go @@ -3,6 +3,7 @@ package dl import ( "bufio" "io" + "log/slog" "regexp" "strconv" "strings" @@ -60,8 +61,11 @@ func parseProgressLine(line string) *progressUpdate { func readProgress(stderr io.ReadCloser, updates chan<- *domain.DownloadJob, job *domain.DownloadJob) { var stderrBuf strings.Builder scanner := bufio.NewScanner(stderr) + lineCount := 0 + matchCount := 0 for scanner.Scan() { line := scanner.Text() + lineCount++ if stderrBuf.Len() < 4096 { stderrBuf.WriteString(line) @@ -72,10 +76,12 @@ func readProgress(stderr io.ReadCloser, updates chan<- *domain.DownloadJob, job if parsed == nil { continue } + matchCount++ job.Progress = parsed.pct job.Speed = parsed.speed job.ETA = parsed.eta updates <- job } job.StderrLog = stderrBuf.String() + slog.Info("readProgress finished", "url", job.URL, "lines", lineCount, "matches", matchCount, "stderr_len", len(job.StderrLog)) } diff --git a/internal/handler/download.go b/internal/handler/download.go index fd5bf5c..f07110c 100644 --- a/internal/handler/download.go +++ b/internal/handler/download.go @@ -396,6 +396,8 @@ func (h *Handler) runDownload(ctx context.Context, job *domain.DownloadJob) { lastProgress := 0.0 for upd := range updates { + slog.Info("progress update", "pct", upd.Progress, "speed", upd.Speed, "status", upd.Status) + h.mu.Lock() currentJob := h.activeJobs[job.UserID] h.mu.Unlock() @@ -419,18 +421,23 @@ func (h *Handler) runDownload(ctx context.Context, job *domain.DownloadJob) { 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 + } 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 { - job.QuotaApplied = true - h.applyQuota(job.UserID, job.FileSize) - } - - kb := progressKeyboard(upd.Progress, upd.Speed, upd.ETA) - text := fmt.Sprintf("Downloading: %s", job.Title) - h.editText(ctx, job.ChatID, job.MessageID, text, &kb) } + + if upd.Progress > domain.QuotaProgressThreshold && !job.QuotaApplied && job.FileSize > 0 { + job.QuotaApplied = true + h.applyQuota(job.UserID, job.FileSize) + } + + kb := progressKeyboard(upd.Progress, upd.Speed, upd.ETA) + text := fmt.Sprintf("Downloading: %s", job.Title) + h.editText(ctx, job.ChatID, job.MessageID, text, &kb) } h.mu.Lock()