Make the worker batch timeout configurable via LIDAR_BATCH_TIMEOUT
The pool of tile workers used to cancel every remaining tile after a
hardcoded 2-hour wall clock, silently truncating large batches (a
670-tile completion run lost its last 348 tiles that way). The timeout
now defaults to unlimited and can be capped per deployment with the
LIDAR_BATCH_TIMEOUT environment variable (seconds); the local worker
compose sets it to 6 hours.
💘 Generated with Crush
Assisted-by: Crush:glm-5.2
This commit is contained in:
@ -47,6 +47,22 @@ def resolve_workers(value):
|
||||
return 1
|
||||
|
||||
|
||||
def _batch_timeout_s():
|
||||
"""Wall-clock budget for one batch, from LIDAR_BATCH_TIMEOUT (seconds).
|
||||
|
||||
Unset, empty or 0 means unlimited (default). A negative or non-numeric
|
||||
value is ignored with a warning.
|
||||
"""
|
||||
raw = (os.environ.get("LIDAR_BATCH_TIMEOUT") or "").strip()
|
||||
if not raw:
|
||||
return 0.0
|
||||
try:
|
||||
return max(0.0, float(raw))
|
||||
except ValueError:
|
||||
logger.warning(f"LIDAR_BATCH_TIMEOUT={raw!r} is not a number — ignored (unlimited)")
|
||||
return 0.0
|
||||
|
||||
|
||||
def _file_basename(path):
|
||||
"""Extract base name from a LAZ/LAS file, removing all known extensions.
|
||||
|
||||
@ -852,15 +868,17 @@ class LidarArchaeoPipeline:
|
||||
for laz_file in files
|
||||
}
|
||||
done = 0
|
||||
t_deadline = time.time() + 7200
|
||||
budget_s = _batch_timeout_s()
|
||||
deadline = time.time() + budget_s if budget_s > 0 else None
|
||||
try:
|
||||
# timeout=: without it, as_completed blocks between two
|
||||
# completions and the 2 h deadline is never evaluated if
|
||||
# no worker returns (run stuck forever).
|
||||
# timeout= lets the deadline be checked between two
|
||||
# completions; without it a stuck worker would block
|
||||
# as_completed forever. No deadline (LIDAR_BATCH_TIMEOUT
|
||||
# unset or 0) → wait indefinitely.
|
||||
as_completed_kwargs = ({"timeout": max(1.0, deadline - time.time())}
|
||||
if deadline is not None else {})
|
||||
try:
|
||||
futures_iter = as_completed(future_to_file,
|
||||
timeout=max(1.0, t_deadline - time.time()))
|
||||
for future in futures_iter:
|
||||
for future in as_completed(future_to_file, **as_completed_kwargs):
|
||||
laz_file = future_to_file[future]
|
||||
done += 1
|
||||
try:
|
||||
@ -877,7 +895,8 @@ class LidarArchaeoPipeline:
|
||||
"tile", "fail", detail=str(e))
|
||||
results[laz_file.name] = False
|
||||
except FuturesTimeoutError:
|
||||
logger.error("Timeout exceeded (2 h) — cancelling remaining workers")
|
||||
logger.error(f"Batch exceeded LIDAR_BATCH_TIMEOUT "
|
||||
f"({budget_s:g} s) — cancelling remaining workers")
|
||||
for f in future_to_file:
|
||||
f.cancel()
|
||||
except KeyboardInterrupt:
|
||||
|
||||
Reference in New Issue
Block a user