Run loop and state¶
process-wikidata (main.run) takes every chunk of a set through processing,
partitioning and upload. pool.py runs the chunks in parallel, and state.py records each
chunk's progress.
Steps of a chunk¶
A chunk's state is a number in state/chunk_{N}.jsonl, one file per chunk:
| Step | Value | Reached when |
|---|---|---|
INIT |
0 | the state is set up (initial.setup_state) |
PULL |
1 | the source file is local and its size checked |
PROCESS |
2 | the seven tables are written to results/{table}/ |
PARTITION |
3 | each table is split into results/{table}/{key}/ |
PUSH |
4 | its group is uploaded |
POST_CHECK |
5 | its group is verified on the Hub |
COMPLETE |
6 | its group's staging is cleaned up |
setup_state creates the files at INIT on the first run: one per chunk in the split
manifest for a release, one per file of the source repo otherwise. get_chunk_state
reads one chunk's file; get_all_state reads every file, which takes about 0.4 s over
13,000 files, so per-chunk code reads only its own.
The loop¶
run():
- Sets up the state if
state/does not exist. - Finishes a group left unfinished by an earlier run (
unfinished_group), from the stage after its last recorded one. - Lists the chunks below
PARTITIONand hands them topool.process_chunks, with the partitioned chunks not yet in a group. - Removes the partition directories left empty by merging.
- Without a release, runs
finalise(). A release's sets are finalised by thereleaserecipe once both are processed.
process_chunks receives the steps as functions:
| Function | Runs in | Does |
|---|---|---|
start(c) |
the parent, before the chunk's process | the pull: dump.check_chunk for a release, pull_chunk and prefetch otherwise |
work(c) |
the chunk's own process | process_and_partition: process, then partition |
done(c) |
the parent, after success | appends the chunk's source and partition bytes to partition_sizes.jsonl |
ready(chunks) |
the parent | whether the closable chunks' partition bytes reach the group threshold |
close(chunks) |
a background thread | merge, upload and verify the group (push) |
Worker processes¶
Each chunk runs in a fresh process, started with spawn. When the process exits, all the
memory it used goes back to the operating system. Native memory freed within one long-lived
process stays with its allocator, and its size grew chunk after chunk. spawn rather than
fork because the parent has threads (the upload thread, the prefetch thread).
CHUNK_WORKERS processes run at once. Each chunk's work is mostly single-threaded, with
parallel stretches in Polars and polars-genson, so one chunk at a time used about half of
a 20-core machine. See Tuning.
Groups with out-of-order chunks¶
A group is a range of consecutive chunk numbers. Chunks finish out of order, so the chunks
that can form a group are the partitioned chunks below every chunk still running or queued
(closable). When their partition bytes reach the threshold, they close as one group in a
background thread, and the workers continue with the next chunks. One group closes at a
time. Once every chunk is done, the remaining partitioned chunks close as the last group.
Failures and interruption¶
- A chunk's process exiting non-zero stops new chunks from starting. The running chunks finish, and then the run raises, naming each failed chunk and its exit code or signal.
- A failed upload raises when the parent next checks the upload thread. Running chunks finish first.
- On Ctrl-C, the chunk processes receive the signal too. The upload thread is a daemon thread and ends with the run; the group ledger resumes the group on the next run.
- An interrupted chunk is redone from its recorded step. Its partly written outputs were
written to
.tmppaths and are overwritten.
Partitioning a chunk¶
partition_chunk checks that every table's processed file exists, prepares each table
(prepare_for_partition) and writes its partitions and audit sidecar, moves the chunk to
PARTITION, and deletes the processed files.
Documented against
Commit 6243a2c (2026-10-04). See About these docs to check for changes.
| File | SHA-256 |
|---|---|
src/wikidata/main.py |
578eeb24bd587fe45e004c8423ff02648c8235b58ddd35714351f9dd2e1ec03c |
src/wikidata/pool.py |
fdb5bb426ceeef9ae4cb3dd1ce649969035a5f21f965b594152995d619bc257a |
src/wikidata/state.py |
23f8bba8b8e9fdc1727ab26d5252b06cac0721a160b0a6cb680adecb958c6429 |
src/wikidata/initial.py |
82eaa1d525ad4a2a02c6c0e35c4581d4b761cf98028c903c3e427ba46e67ad64 |