fix(operator): interpolate desc.url so failure message shows the URL#6800
Conversation
In URLFetcherOpExec, the fetch-failure fallback used `s"...$desc.url"`,
which expands only `$desc` (the URLFetcherOpDesc instance) and appends a
literal `.url`. Because LogicalOp overrides toString with
ToStringBuilder.reflectionToString, the "URL content" cell got the whole
descriptor dump (operatorId, inputPorts, dummyPropertyList, ...) instead
of the URL.
Wrap the member access in braces (`${desc.url}`) so the message reads
`Fetch failed for URL: <url>` as intended and stops leaking internal
operator fields into user-facing output.
Closes apache#6755
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Automated Reviewer SuggestionsBased on the
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #6800 +/- ##
============================================
- Coverage 77.30% 75.93% -1.37%
- Complexity 3524 3570 +46
============================================
Files 1161 1174 +13
Lines 45922 46861 +939
Branches 5101 5207 +106
============================================
+ Hits 35501 35586 +85
- Misses 8840 9649 +809
- Partials 1581 1626 +45
*This pull request uses carry forward flags. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
| config | throughput | MB/s | latency | max Δ latest / 7d | |
|---|---|---|---|---|---|
| 🟢 | bs=10 sw=10 sl=64 | 356 | 0.217 | 26,579/36,712/36,712 us | 🟢 -5.7% / 🔴 +121.2% |
| 🔴 | bs=100 sw=10 sl=64 | 785 | 0.479 | 127,061/155,476/155,476 us | 🔴 +14.4% / 🔴 +42.5% |
| 🔴 | bs=1000 sw=10 sl=64 | 893 | 0.545 | 1,115,652/1,231,489/1,231,489 us | 🔴 +6.8% / 🔴 +17.7% |
Baseline details
Latest main f02dd2f from same runner
| config | metric | PR | latest main | 7d avg | Δ latest | Δ 7d |
|---|---|---|---|---|---|---|
| bs=10 sw=10 sl=64 | throughput | 356 tuples/sec | 372 tuples/sec | 754.55 tuples/sec | -4.3% | -52.8% |
| bs=10 sw=10 sl=64 | MB/s | 0.217 MB/s | 0.227 MB/s | 0.461 MB/s | -4.4% | -52.9% |
| bs=10 sw=10 sl=64 | p50 | 26,579 us | 25,686 us | 12,816 us | +3.5% | +107.4% |
| bs=10 sw=10 sl=64 | p95 | 36,712 us | 38,942 us | 16,594 us | -5.7% | +121.2% |
| bs=10 sw=10 sl=64 | p99 | 36,712 us | 38,942 us | 19,806 us | -5.7% | +85.4% |
| bs=100 sw=10 sl=64 | throughput | 785 tuples/sec | 811 tuples/sec | 969.38 tuples/sec | -3.2% | -19.0% |
| bs=100 sw=10 sl=64 | MB/s | 0.479 MB/s | 0.495 MB/s | 0.592 MB/s | -3.2% | -19.0% |
| bs=100 sw=10 sl=64 | p50 | 127,061 us | 123,538 us | 103,584 us | +2.9% | +22.7% |
| bs=100 sw=10 sl=64 | p95 | 155,476 us | 135,935 us | 109,097 us | +14.4% | +42.5% |
| bs=100 sw=10 sl=64 | p99 | 155,476 us | 135,935 us | 117,304 us | +14.4% | +32.5% |
| bs=1000 sw=10 sl=64 | throughput | 893 tuples/sec | 892 tuples/sec | 1,004 tuples/sec | +0.1% | -11.0% |
| bs=1000 sw=10 sl=64 | MB/s | 0.545 MB/s | 0.545 MB/s | 0.613 MB/s | 0.0% | -11.0% |
| bs=1000 sw=10 sl=64 | p50 | 1,115,652 us | 1,118,143 us | 1,002,357 us | -0.2% | +11.3% |
| bs=1000 sw=10 sl=64 | p95 | 1,231,489 us | 1,153,307 us | 1,046,463 us | +6.8% | +17.7% |
| bs=1000 sw=10 sl=64 | p99 | 1,231,489 us | 1,153,307 us | 1,073,661 us | +6.8% | +14.7% |
Raw CSV
config_idx,batch_size,schema_width,string_len,num_batches,total_ms,total_tuples,total_bytes,tuples_per_sec,mb_per_sec,lat_p50_us,lat_p95_us,lat_p99_us
0,10,10,64,20,561.98,200,128000,356,0.217,26578.80,36712.46,36712.46
1,100,10,64,20,2548.83,2000,1280000,785,0.479,127060.87,155475.98,155475.98
2,1000,10,64,20,22403.70,20000,12800000,893,0.545,1115652.39,1231489.30,1231489.30|
@Yicong-Huang May you take a look at it please? |
Yicong-Huang
left a comment
There was a problem hiding this comment.
LGTM, thanks for the fix
Yicong-Huang
left a comment
There was a problem hiding this comment.
still would be good to add a regression test. if URLFetcher has no tests, let's add them in this PR.
…essage
Assert the fetch-failure fallback interpolates `desc.url` itself, not the
URLFetcherOpDesc reflectionToString dump. Uses a file:// URL to a nonexistent
path so getInputStreamFromURL returns None deterministically and offline (no
network), exercising the failure branch without external connectivity.
Verified: passes with the ${desc.url} fix, fails with the pre-fix $desc.url.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
891e204 to
86cd1c4
Compare
|
Done. Added regression test. |
There was a problem hiding this comment.
Pull request overview
Fixes a Scala string interpolation bug in the URL Fetcher source operator so the fetch-failure fallback message shows only the URL (and avoids leaking the full operator descriptor’s toString dump into user-facing output).
Changes:
- Fix string interpolation in
URLFetcherOpExecfailure-path message by interpolating${desc.url}. - Add a regression test that exercises the failure branch offline and asserts the message contains only the URL (and not descriptor fields).
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| common/workflow-operator/src/main/scala/org/apache/texera/amber/operator/source/fetcher/URLFetcherOpExec.scala | Fixes failure message interpolation to use desc.url correctly. |
| common/workflow-operator/src/test/scala/org/apache/texera/amber/operator/source/fetcher/URLFetcherOpExecSpec.scala | Adds regression coverage for the failure-path message content. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Signed-off-by: Kary Zheng <150742834+kz930@users.noreply.github.com>
|
Resolved Copilot comment. CI is green. |
|
thanks @kz930 . @aglinxinyuan codecov is not updating. please check. |
|
Dug in. The deferred codecov-action re-downloads and verifies the CLI on every leg, importing Codecov's key at runtime, and that key import flakes — a random leg dies while its siblings upload fine. With Fix in #6836: each upload retries once, so a transient CLI/GPG flake self-heals while a genuine failure still surfaces. Verification stays intact (no For #6800 specifically: its latest head is still working through the ASF runner backlog, so it should refresh once that Required Checks run + the deferred upload finish. If the upload flakes on it before #6836 lands, the quickest unblock is to re-run the failed |
|
Now with the #6840 reverting the change, I am rerunning CI. If coverage looks good we can proceed to merge. |
|
The CI is green now. |
|
still not seeing codecov change. Rerunning CI again |
…nch-covered JaCoCo marks the `case None` line of the Option match as partially covered because the match carries an unreachable MatchError branch, which makes Codecov count the patched line as uncovered (patch 0%). getOrElse expresses the same fallback without a pattern match, so the line is fully covered by the existing regression test. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
cc @xuang7 for review to v1.2 |
|
lets backport separately. |
What changes were proposed in this PR?
Fixes a Scala string-interpolation bug in
URLFetcherOpExec's fetch-failure fallback.The failure branch built its message with
s"Fetch failed for URL: $desc.url". In ans"..."interpolator,$descexpands only the identifierdesc(theURLFetcherOpDescinstance) and.urlis appended as literal text. BecauseLogicalOpoverridestoStringwithToStringBuilder.reflectionToString, the resultingURL contentcell contained the entire descriptor dump instead of the URL:This both malforms the message and leaks internal operator fields (
operatorId,inputPorts,dummyPropertyList, …) into user-facing output.The fix wraps the member access in braces so only
desc.urlis interpolated:Now the message reads as intended:
Any related issues, documentation, discussions?
Closes #6755
How was this PR tested?
Added an automated regression test to
URLFetcherOpExecSpecthat exercises the fetch-failure branch offline and deterministically: pointing the operator at afile://URL for a nonexistent path makesURLFetchUtil.getInputStreamFromURLreturnNonewith no network dependency. The test asserts the fallback cell is exactlyFetch failed for URL: <url>and does not contain the descriptor dump (URLFetcherOpDesc,operatorId, …), so it fails on the pre-fix$desc.urlbehavior and passes with the fix.Also reproduced end-to-end before the fix by pointing a URL Fetcher operator at an unreachable address (
https://this-host-does-not-exist.invalid/x) and inspecting theURL contentoutput cell: it showed the fullURLFetcherOpDesc[...]dump followed by.url; after the fix it showsFetch failed for URL: https://this-host-does-not-exist.invalid/x.Was this PR authored or co-authored using generative AI tooling?
Generated-by: Claude Code (Claude Opus 4.8)