Skip to content

qvd2parquet v2.1.0

Choose a tag to compare

@github-actions github-actions released this 25 Aug 16:14
· 18 commits to main since this release
2e78542

The quality gate stops being the slow, silent, uninterruptible part of a wide
conversion. Everything here follows from running 2.0.0 on the SAP extract that
prompted it: the gate is now the default, and on a 20.6M-row, 213-column file
it ran for about twenty minutes at 11% CPU, printing nothing and ignoring
Ctrl-C.

Added

  • The quality gate reads the output back in parallel, splitting it across
    workers by row group the same way decoding is split by chunk. It was entirely
    single-threaded, which on a wide file left the machine idle for minutes at
    the end of every run: on a 213-column, 1M-row fixture the full gate takes
    60.9s single-threaded and 9.3s at eight workers, cutting the whole run from
    4.7x the conversion to 2.6x. Row groups are independent, and both the metrics
    and the fingerprint merge in any order -- which is what already let parallel
    decoding validate without reordering -- so the verdict does not depend on the
    worker count. Each worker opens its own handle, for the same reason the
    decode workers do.

  • The quality gate reports progress on the --progress cadence, which is on by
    default. It previously printed nothing until it finished, so a run that was
    working looked like one that had hung.

  • Ctrl-C and SIGTERM now shut down gracefully and report themselves as what
    they are. A cancelled run stops at the next chunk boundary, drains what is in
    flight, removes the temporary output and exits with a new code 7.

    It previously exited 4, input error, with wrote 234725 rows but the header declares 1000000 -- a stopped run has written fewer rows than the
    header declares, which is exactly what a truncated input looks like, so
    pressing Ctrl-C told the user their QVD was corrupt. A cancelled quality gate
    likewise reported a gate failure, as though the output had not matched its
    input, when nobody had finished looking.

    A temporary output that cannot be deleted is now reported and named, instead
    of the failure being discarded and a partial Parquet file left sitting beside
    the real one. The delete is retried briefly first: Windows refuses to remove
    a file while any handle is open, and a virus scanner or the search indexer
    routinely holds one for a moment on a file just written, so the first attempt
    can fail on a file that is about to be perfectly deletable.

    In batch mode the files not yet started are recorded as cancelled too, rather
    than carrying a bare context.Canceled that mapped to the input-error code
    and reported unattempted files as unreadable ones. A cancelled batch
    outranks any individual file's verdict in the summary, since the rest were
    never tried.

    The signal handler is written against an explicit channel rather than
    signal.NotifyContext, whose stop function cancels the context as well as
    unregistering the handler: a goroutine waiting on Done cannot tell a real
    signal from the deferred cleanup of a successful run, and announced a
    cancellation on 37 of 40 successful conversions.

    The quality gate also honours cancellation at all now: it ran on
    context.Background(), so Ctrl-C during the read-back did nothing whatsoever
    -- on a wide file, minutes of a signal being ignored. And because
    signal.NotifyContext keeps swallowing signals once it has fired, a second
    Ctrl-C did nothing either. The first signal now restores the default handler
    and says so, so an impatient second one stops the process outright.

Install

Download the archive for your platform below, unpack it, and put qvd2parquet
on your PATH. Verify the download against SHA256SUMS:

shasum -a 256 -c SHA256SUMS --ignore-missing

Binaries are pure Go and statically linked, so they need no runtime
dependencies: Linux (amd64, arm64), Windows (amd64, arm64) and macOS (amd64,
arm64).