pyvips redirects all GLib messages ("VIPS: threadpool completed ..."
per operation) onto the 'pyvips' logger at INFO. The helper caps that
logger at WARNING while keeping 'pyvips.voperation' (deprecated-argument
notices) at INFO. Library import remains free of logging side effects;
the CLI and worker entry points call the helper instead of their old
bare setLevel, which also hid the deprecation notices.
The temporary HTTP server that OnlyOffice downloads the source document
from was bound to 0.0.0.0, so internet scanners could (and did) connect,
and socketserver dumped a full traceback to stderr for every dropped
connection. It also stayed up for the whole conversion attempt, leaving
the port exposed when conversions hang.
- Bind only to the callback host (oonet gateway by default) so the port
is unreachable from the internet.
- Override handle_error to log at debug level instead of printing
tracebacks.
- Watchdog shuts the server down ~2s after the file is fetched, or at
max_lifetime (request_timeout + 30s), and the socket is closed with
server_close() in the normal path.
The cista service account has no docker CLI access, so detecting the
gateway via docker network inspect silently fell back to docker0/legacy
behavior. With the pinned subnet the gateway is always 172.30.0.1;
ONLYOFFICE_CALLBACK_HOST remains as an env override.
The container always lives on the isolated oonet network at the fixed
IP; falling back to a published localhost port silently masked broken
setups with confusing 'not reachable at localhost:8988' diagnostics.
Docker silently discards published ports on internal networks, so the
isolated oonet setup left the container unreachable at localhost:8988.
Reach it at its fixed IP (172.30.0.2) on the bridge instead; the host
is the gateway, so this needs no port publishing at all. The oosetup
CLI drops its now-meaningless <port> argument.
Also: record whether OnlyOffice fetched the input file from the
temporary callback server and report it in the timeout error message
('input file never fetched' = network/callback failure, vs a stalled
conversion). Convert POST timeout is 7s (conversion runs inside the
request), result PNG download stays at 2s.
- Dockerfile: pin ONLYOFFICE server sources to a known-good commit
(build-arg ONLYOFFICE_SERVER_REF) instead of tracking master; master
gained a 'memory runtime' branch that forks no converter workers on
community edition, silently breaking all conversions. Also patch that
branch out as defense in depth.
- setup_docker: run the container on an internal-only network (oonet,
172.30.0.0/24) with no outbound internet; only host callback traffic
is possible.
- _get_callback_host: resolve the oonet gateway via docker network
inspect instead of assuming docker0; fall back to docker0.
- OOConversionManager: cancel the background conversion task when its
last waiter is cancelled (strict preview deadline), releasing the
semaphore slot and aborting the hung HTTP request; shield the shared
future so one waiter's cancellation does not affect others.
- Split timeouts: convert POST 7s (conversion happens inside the
request with async:false), result PNG download 2s.
Worker logs expected PreviewError failures as warnings; tracebacks are
reserved for unanticipated internal errors. pdf read errors report
backend "pdf" (vips not yet reached); the stage field is dropped as the
backend name now encodes the failing pipeline step. Backend label
"pyvips" renamed to "vips" everywhere.
PreviewError subclasses carry a concise short label for UI, a full log
message, backend name, and metadata fields (OnlyOffice code/status/url,
backend stage, timeout seconds, cancel reason). Exceptions travel across
the worker pool wire pickled in the binary response payload (ok=False)
and are re-raised with their original type on the caller side. Combined
pipelines such as pdf+pyvips tag the failing stage.
Add fixtures and tests covering image EXIF orientations, HDR AVIF, SDR video, 90/270 rotated video, HDR video with and without rotation, PDF, dispatch, and OnlyOffice (skipped unless configured).
Regenerate rotated/HDR video fixtures and sample.pdf with tests/files/generate_fixtures.py.
- Accept a keyframe with pts as well as dts, so all-intra or short HDR clips are not rejected as No frames found.
- Round resized video dimensions to multiples of 2 (width) and 4 (height) so planar 4:2:0 YUV rotation always works.
- Use abs(frame.rotation) when swapping display dimensions, so both +90 and -90 rotation matrices report the correct orientation.
- __main__ is now a self-contained docopt CLI going straight to
backends.dispatch (no blake3/tracerite needed); 'oosetup' builds and
starts the bundled OnlyOffice container and prints
ONLYOFFICE_JWT_SECRET=<token> as its only stdout line
- dispatch: log a plain one-line error for missing-extra ImportErrors
instead of a traceback
- worker/pool: friendly install hints when the 'worker' extra is missing
- office: fix import on Python 3.11-3.13 without the 'office' extra
(lazy annotations); setup_docker returns the JWT secret used and
redacts it from the logged docker command
- add 'mediapreview' console script and docopt-ng dependency