Show a determinate progress bar during export
The export loop can run for a while on large lists. It already knows the message count up front, so draw a braille spinner + progress bar (frames and blue borrowed from warez) from inside the Python loop. Written to stderr so it never pollutes the captured MM3HK| stdout, gated on isatty() so cron/piped runs stay silent, throttled to ~10 fps, cleared in finally. Progress bytes never touch the mbox, so its SHA-256 is unaffected.
This commit is contained in:
parent
8b00e239d2
commit
a39ca3157f
1 changed files with 23 additions and 2 deletions
|
|
@ -73,7 +73,7 @@ EOF
|
|||
}
|
||||
|
||||
result=$(mailman-web shell <<EOF
|
||||
import sys, os, tempfile, gzip, hashlib
|
||||
import sys, os, tempfile, gzip, hashlib, time
|
||||
from hyperkitty.models import MailingList
|
||||
addr = "$addr"
|
||||
GZIP = $gzip_py
|
||||
|
|
@ -96,14 +96,35 @@ raw = os.fdopen(fd, "w+b")
|
|||
# mtime=0 keeps the gzip header deterministic (no timestamp), matching the
|
||||
# web export, which uses a bare zlib gzip stream.
|
||||
fh = gzip.GzipFile(fileobj=raw, mode="wb", mtime=0) if GZIP else raw
|
||||
# Live progress bar on stderr: stdout is captured by the shell (the MM3HK|
|
||||
# line), so a shell-side spinner can't see per-message progress, but this loop
|
||||
# knows n up front. TTY-only, so cron/piped runs stay silent. Braille frames
|
||||
# and blue borrowed from warez's spinner.
|
||||
tty = sys.stderr.isatty()
|
||||
SPIN = "⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏"
|
||||
def draw(done, spin):
|
||||
w = 24
|
||||
fill = done * w // n
|
||||
sys.stderr.write("\r\033[0;34m%s\033[0m [%s%s] %d/%d (%d%%)" % (
|
||||
SPIN[spin % len(SPIN)], "█" * fill, "░" * (w - fill),
|
||||
done, n, done * 100 // n))
|
||||
sys.stderr.flush()
|
||||
spin = 0
|
||||
last = 0.0
|
||||
try:
|
||||
for e in ml.emails.order_by("archived_date").iterator():
|
||||
for i, e in enumerate(ml.emails.order_by("archived_date").iterator(), 1):
|
||||
fh.write(e.as_bytes())
|
||||
fh.write(b"\n\n")
|
||||
if tty:
|
||||
now = time.monotonic()
|
||||
if now - last >= 0.1 or i == n: # ~10 fps, plus a final 100% frame
|
||||
draw(i, spin); spin += 1; last = now
|
||||
finally:
|
||||
if GZIP:
|
||||
fh.close() # flush the gzip trailer into raw (does not close raw)
|
||||
raw.flush()
|
||||
if tty:
|
||||
sys.stderr.write("\r\033[K"); sys.stderr.flush() # clear the bar
|
||||
# Hash the on-disk bytes via the held fd, then hand root the digest so it can
|
||||
# verify the file wasn't swapped/truncated by another same-uid process before
|
||||
# it copies it. (A fully-compromised exporter is out of scope, since it controls
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue