Adom Step2GLB - The Adom STEP Engine
Public Made by Adomby adom
The Adom STEP engine: fully manage STEP files. Convert to color-preserving GLB, render thumbnails and vector outlines, laser-etch MPNs, create and edit STEP geometry, extract features, and run molecule mode. One name for the thin Rust CLI and the shared OCCT service. Formerly 'step2glb' + 'service-step2glb'.
/outline cannot process a large board STEP: hard 170s worker timeout, fails at any memory cap
POST /outline cannot process a large board STEP. The OCCT-HLR worker is run with a hard 170-second subprocess timeout, and a 31.5 MB board exhausts it every time, on a container with 16 GB and four idle workers.
This is a compute-time limit, not a memory limit: the job fails at any memory cap. Raising the container's memory would not change it.
Reproducer
Input: bq25792-charger.step (31.5 MB), the STEP published on adom/bq25792-charger.
curl -X POST "$SERVICE/outline?upAxis=z" -H 'X-Client: …' -H 'X-Job-Name: …' \
--data-binary @bq25792-charger.step
Every job reports status: failed after ~176 s wall:
outline worker exited 1 | …
subprocess.TimeoutExpired: Command '[…/occt_outline.py, …/in.step, …, 'chip', 'z', '--rot', '180']'
timed out after 170 seconds
Job ids, all against occt-fbnsqrdkehdj on 1.3.4 dcde0b9a: 873d1a204a6c4eba (single), then 0fea99c3ae14d00c, e40a956704f9268f, 7227d5b0093bde55, e761fba36446cdea (four concurrent).
The job's own hint is good and correctly points away from an input fault:
resource fault (memory/time), not an input fault: re-submit when the service is quieter (GET /health shows workers), or split the model
but re-submitting when quieter does not help, because the limit is per-job wall time, not contention. A single job on an otherwise idle container fails identically.
Where it is
api/occt/outline_job.py:41
r = subprocess.run(cmd, capture_output=True, text=True, timeout=170)
api/occt/name_emboss_job.py:55 carries the same constant, so /name-emboss has the same ceiling.
Measured cost
From a memory-instrumented run on the 16 GB container (cgroup memory.current, sampled 4×/s):
| peak, one job | 2.88 GB |
| peak, four concurrent jobs | 10.12 GB of the 16 GB cap |
| swap growth across the run | +6.9 MB (negligible) |
| wall time per job | ~176 s, all four hitting the 170 s cap |
So the work is memory-feasible and simply does not finish. Four ran side by side with 5.9 GB to spare.
Please do not just raise the constant
The right question is where the time goes. OCCT HLR on a model with this many faces is the likely sink, and /outline renders 16 styles, so a per-style cost is multiplied. Worth measuring before changing the number: per-style timing, whether styles share one HLR projection or recompute it, and whether a face-count threshold should decimate or refuse with a clear message rather than burn 170 s and fail.
Relationship to #9 — different fault, do not merge them
#9 (John) is not this. His three failing files are ~0.3 MB and report "unknown error" with duration_seconds: null, i.e. they die immediately with empty stderr — the signal/segfault path described in the reply on that issue. This one is a 31.5 MB file that runs the full 170 s and fails with a named TimeoutExpired. A 0.3 MB part cannot exhaust a 170 s HLR budget; a 0.2 MB part outlines in a couple of seconds on the same service. Same endpoint, two distinct mechanisms.
Found while running the standby-container endpoint parity diff; both containers fail this identically, so it is not a standby regression.