Skip to content

v0.9.0

Choose a tag to compare

@cboettig cboettig released this 29 Sep 20:25
· 32 commits to main since this release
862629d

Added

  • workflow --chunk-size N sets the number of features per hex chunk (#237). The generator never went below 1000 features per chunk, and no flag could change that, so any vector dataset under 1000 features got a single hex pod however large its polygons were. Hex memory follows the H3 cells of the features in a chunk, not how many features there are, so a small-count, large-feature layer is exactly the case that needs small chunks. The 847-feature ecoregions layer at res 8 now generates the 170 × 5 fan-out that production runs from a hand-tuned manifest. The default is unchanged. If the requested size would need more than --max-completions chunks, it is still raised to fit, and the generator now says so instead of overriding an explicit memory decision without a word. This is a manual control; sizing chunks automatically from feature size is #124.

Changed

  • Behaviour change: vector hex chunks are planned by estimated H3 cells, not a fixed feature count (#124). A hex pod's memory and runtime follow its features' cells, and those are extremely skewed: on IUCN ranges at res 6 the median feature is 345 cells and the largest 2.5 M. Measured on three published layers, the largest chunk under the fixed rule was 2.2–2.4× the mean (207 M cells on EPA L4 ecoregions), and lowering the count by hand made it worse (8–36×). workflow now emits a plan step between convert and hex. cng-datasets vector-plan estimates each row's cells and cuts the GeoParquet into contiguous row ranges at a cells budget (--cells-per-chunk, default 5 M), never exceeding the old 1,000 features per chunk. Point layers are therefore chunked as before, and heavy polygons are split further; the same three layers balanced to 1.0–1.2×. The plan pod reports its chunk count as its termination message, and the orchestrator patches the hex Job's completions to match before applying it. The hex YAML as generated carries an upper bound (min(--max-completions, rows)), so apply it through workflow.yaml. A hex index past the end of the plan exits cleanly; that is the fallback for a hand-applied or Armada hex job. If the budget needs more chunks than --max-completions allows, it is raised to fit, with a warning. A plan that no longer matches the GeoParquet fails the hex pod instead of dropping rows. --chunk-size N (#237) still gives fixed chunks and turns planning off.

Fixed

  • Vector hex pods bound DuckDB to the pod, not the node (#255). Vector DuckDB connections never set memory_limit, so DuckDB sized its buffer manager at 80% of the node's RAM: an 8Gi hex pod on a 250 GiB node believed it had about 200 GiB. It never spilled, and a large feature was OOM-killed by the cgroup instead. The raster hex step had the same bug, fixed in #227. The vector hex job now carries DUCKDB_MEMORY_LIMIT at 85% of --hex-memory, and every vector DuckDB connection applies it, normalising Kubernetes spellings like 8Gi (#217). Hex pods now spill to /tmp where they used to be killed, so a very large feature may need more --hex-storage.
  • Workflow orchestrators stop when a step fails, instead of waiting out its timeout (#258). Each step was awaited with kubectl wait --for=condition=complete, which never returns for a Job that has failed. A dead hex step therefore held the vector orchestrator for its full 48 h, looking Running throughout. Both the vector and raster orchestrators now wait with a wait_job helper that returns on Complete and exits immediately on Failed, printing the Job's failure reason and the kubectl logs command to run. Repartition's incomplete-output error now lists a failed hex index as the likeliest cause, ahead of the #170 truncation it used to blame.
  • The oversized-feature guard works everywhere, not just between 90°W and 90°E (#253). The #107 guard measures each feature with DuckDB's ST_Area_Spheroid, which reads coordinates as (latitude, longitude), while every geometry here is (longitude, latitude). Any feature beyond ±90° longitude measured NaN. Because NaN sorts above every number, one such feature also hid the chunk's real worst feature, so the guard was off for any chunk touching the Americas west of the Mississippi, East Asia or Australia. There, an oversized feature hit the raw C++ page-size assertion again instead of the guard's clear error. On the published ecoregions layers, 404 of 847 and 4,007 of 5,896 features measured NaN. Areas are now computed on flipped axes and match a known answer at any longitude. Output data was never affected; only the guard.