synology_apm_repo.sdk.presentation.progress module¶
Progress/ProgressMeter: the one progress contract CLI and
TUI both build on, so neither grows its own rate/ETA math that disagrees
with the other’s.
Four rules, implemented here rather than left to each caller to reinvent:
The denominator is planned work, not logical size — a caller’s job; this module just carries whatever
totalit’s given (e.g. a sparse image only needs the chunks a planning pass found, not its full logical size).Rate is a windowed average over the last
rate_window_secondsof real elapsed time, not a cumulative average (mis-predicts ETA right after a rate change) and not a per-call EWMA (a burst of near-zero-dtcalls would drag a constant-α blend up to a spike value). ETA is suppressed until enough time/progress has accumulated (a warm-up window), and reported quantized so it doesn’t jitter.New rate samples are taken no more often than
rate_sample_interval, decoupling how often the windowed average is recomputed from how oftenProgressMeter.updateis called — this is what makes rule 2’s fix actually hold, and keeps the sample deque bounded regardless of real call frequency.Reporting itself is rate-limited inside the SDK — calling a UI callback per chunk would cost more than the decode it measures.
ProgressMeter.updateis cheap to call every tick; it only forwards to the wrapped callback everymin_intervalseconds ormin_deltaunits, whichever comes first.
- class synology_apm_repo.sdk.presentation.progress.Progress(phase, determinate, done=0, total=None, unit='bytes', detail='', found=None)¶
Bases:
objectOne snapshot of a long-running operation’s state.
- Variables:
phase (str) –
"discovering","planning","reading","assembling", or"verifying".determinate (bool) – Whether
totalis meaningful.total (int | None) –
Nonewhen the total is unknown.unit (str) –
"bytes","items","chunks", or"buckets".detail (str) – The file/object currently being processed, for UI display.
found (int | None) – Incremental result count when
totalis unknown.
- class synology_apm_repo.sdk.presentation.progress.ProgressMeter(callback=None, *, min_interval=0.1, min_delta=0, rate_window_seconds=3.0, rate_sample_interval=0.2, eta_warmup_seconds=2.0, eta_warmup_fraction=0.01, now=<built-in function monotonic>)¶
Bases:
objectSmooths raw
Progresssnapshots into a stable rate/ETA (rules 2-3) and rate-limits how often the wrapped callback actually fires (rule 4). Construct one per operation; callupdateas often as convenient (every chunk is fine).- async update(progress)¶
Record
progressand, if rule 4’s throttle says so, notify.async defeven though the sampling arithmetic itself is pure: the callback isAwaitable, so making this method async (rather than sync with a fire-and-forget Task) is what keeps back-pressure intact — a slow UI callback slows the producer down instead of piling up unawaited Tasks. The callback is awaited only when the throttle decides to notify, so the per-tick cost stays cheap.
- synology_apm_repo.sdk.presentation.progress.reading_progress_callback(meter)¶
Adapts
meterto the raw(done, total)shapeContentSource.export_to’s ownprogresscallback calls, as aphase="reading"byte count — the one adapter both the CLI’sexportcommand and the TUI’s export screen need, so a UI-facing “rate”/”ETA” can never disagree about what a raw export callback’s numbers mean.