Skip to content

Commit a597e35

Browse files
timsaucerclaude
andcommitted
Close the review's smaller findings
- Ignore the .arrow.tmp files a crash mid-write leaves behind, not just the published shuffle output. - The capsule-protocol skill's rule on fallback was categorical; the distributed example is the repository's first legitimate exception, and an agent following the skill would have "fixed" it into breakage. The skill now carves out the rewriting planner and points at the guide. - A non-UTF-8 table directory was lossily mangled into the logical payload while file paths in the same function were rejected outright; both are rejected now. - dfx-udfs declared datafusion-common and datafusion-expr and used neither; a crate meant to be copied should not carry a misleading dependency list. - build.yml states the assumption container:off makes about build and test landing on the same runner image, and both ways out if it ever bites. - test.yml runs run_tpch.py against the dataset it already generates, so the script the README advertises cannot rot while its suites stay green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 1126c6a commit a597e35

7 files changed

Lines changed: 31 additions & 8 deletions

File tree

.ai/skills/ffi-capsule-protocol/SKILL.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,13 @@ above: it takes a second argument, the planner assembled so far. A session has
6767
one planner slot, so planners compose by nesting rather than by chaining, and
6868
the host hands each bundle the previous layer instead of letting it capture one.
6969
Wrap `fallback` and delegate to it; returning a planner that ignores it discards
70-
every layer beneath, including one the session already had. It runs after every
71-
bundle's codecs are installed, so `ctx` carries the final chains.
70+
every layer beneath, including one the session already had. The one legitimate
71+
exception is a planner that *rewrites* the plan (splitting it into stages, say):
72+
it cannot delegate, because a fallback returns nodes it can neither downcast nor
73+
serialize, so it plans for itself against its own optimizer rules —
74+
`examples/distributed/engine-library` is the worked case, and
75+
`docs/source/extension-guide/query-planners.md` argues it. The hook runs after
76+
every bundle's codecs are installed, so `ctx` carries the final chains.
7277

7378
That is also the only hook where it does. `__datafusion_session_components__`
7479
runs before anything is installed, so its `ctx` still carries the chains the

.github/workflows/build.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,13 @@ jobs:
192192
# container, which drops a container start and an in-container rustup
193193
# install per library and lets the Swatinem/rust-cache above cover them.
194194
#
195+
# "A runner like this one" is an assumption, not a guarantee: build and
196+
# test are separate jobs, and during GitHub's ubuntu-latest image
197+
# migrations they can land on different images. A wheel built against a
198+
# newer glibc then fails to import on the test runner. If that ever
199+
# bites, pin both jobs to the same explicit image -- or put these builds
200+
# back in the manylinux container, which made it impossible.
201+
#
195202
# None of them pass `target`, so their artifacts land in `target/debug`
196203
# alongside the priming build's. Naming a target would move them under
197204
# `target/<triple>/debug` and the priming build would be wasted.

.github/workflows/test.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,3 +163,12 @@ jobs:
163163
run: |
164164
cd examples/tpch
165165
uv run --no-project pytest _tests.py
166+
167+
# The script the distributed example's README advertises, against the
168+
# dataset generated above -- so the exact entry point a reader will
169+
# copy-paste cannot rot while its test suite stays green. The row cap
170+
# keeps the reshard and the worker round trip to seconds; correctness
171+
# on the full shape is the pytest suites' job, this is the script.
172+
- name: Run distributed TPC-H example
173+
if: matrix.wheel-tag == 'abi3'
174+
run: uv run --no-project python examples/distributed/run_tpch.py --rows 400000

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,6 @@ examples/distributed/*/uv.lock
4444
# directory, so one appearing in the tree means a relative shuffle_dir
4545
# reached a stage node and the files landed in the working directory
4646
# instead -- which is how three of them were committed once already.
47-
examples/distributed/**/stage-*-part-*.arrow
47+
# The trailing `*` also catches the `.<pid>-<n>.arrow.tmp` files a
48+
# writer stages before its rename, which a crash mid-write leaves behind.
49+
examples/distributed/**/stage-*-part-*.arrow*

Cargo.lock

Lines changed: 0 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/distributed/storage-library/src/table_provider.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,12 @@ impl PartitionedParquetTable {
114114
Some(schema) => schema,
115115
None => Arc::new(Self::read_schema(&paths[0])?),
116116
};
117+
let directory = directory
118+
.to_str()
119+
.ok_or_else(|| DataFusionError::Plan(format!("non-UTF-8 path {directory:?}")))?
120+
.to_string();
117121
Ok(Self {
118-
directory: directory.to_string_lossy().into_owned(),
122+
directory,
119123
files,
120124
schema,
121125
})

examples/distributed/udf-library/Cargo.toml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,6 @@ publish = false
3030
arrow = { workspace = true }
3131
arrow-schema = { workspace = true }
3232
datafusion = { workspace = true }
33-
datafusion-common = { workspace = true, default-features = false }
34-
datafusion-expr = { workspace = true }
3533
datafusion-ffi = { workspace = true }
3634
datafusion-functions-window = { workspace = true }
3735
datafusion-proto = { workspace = true }

0 commit comments

Comments
 (0)