qvd2parquet v2.1.0
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 thefullgate 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
--progresscadence, 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
SIGTERMnow 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 code7.It previously exited
4,input error, withwrote 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 barecontext.Canceledthat 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 onDonecannot 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.NotifyContextkeeps 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-missingBinaries are pure Go and statically linked, so they need no runtime
dependencies: Linux (amd64, arm64), Windows (amd64, arm64) and macOS (amd64,
arm64).