This is an automated email from the ASF dual-hosted git repository.
xuang7 pushed a commit to branch release/v1.2
in repository https://gitbox.apache.org/repos/asf/texera.git
The following commit(s) were added to refs/heads/release/v1.2 by this push:
new 9c446a6294 fix(operator, v1.2): interpolate desc.url so failure
message shows the URL (#6996)
9c446a6294 is described below
commit 9c446a629476d8a1b20e5f8e7baea55ef45490ef
Author: Yicong Huang <[email protected]>
AuthorDate: Wed Jul 29 14:08:26 2026 -0400
fix(operator, v1.2): interpolate desc.url so failure message shows the URL
(#6996)
### What changes were proposed in this PR?
Backport of #6800 to `release/v1.2`, cherry-picked from
97f0fdb43fa7e14a501237a9f6662d7dd2ddbf56. The cherry-pick applied
cleanly.
Follows the Direct Backport Push convention; opened as a PR (rather than
a direct push) per a backport-coverage audit.
### Any related issues, documentation, discussions?
Backport of #6800. Originally linked #6755.
### How was this PR tested?
Release-branch CI runs on this PR. Cherry-pick applied cleanly onto
`release/v1.2`; no manual conflict resolution was needed.
### Was this PR authored or co-authored using generative AI tooling?
Yes — backport prepared with Claude Code (mechanical cherry-pick; the
change itself is #6800 by its original author).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Signed-off-by: Kary Zheng <[email protected]>
Co-authored-by: Kary Zheng <[email protected]>
Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]>
Co-authored-by: Copilot Autofix powered by AI
<[email protected]>
Co-authored-by: Xinyuan Lin <[email protected]>
---
.../operator/source/fetcher/URLFetcherOpExec.scala | 8 +++-----
.../source/fetcher/URLFetcherOpExecSpec.scala | 23 ++++++++++++++++++++++
2 files changed, 26 insertions(+), 5 deletions(-)
diff --git
a/common/workflow-operator/src/main/scala/org/apache/texera/amber/operator/source/fetcher/URLFetcherOpExec.scala
b/common/workflow-operator/src/main/scala/org/apache/texera/amber/operator/source/fetcher/URLFetcherOpExec.scala
index 3f7b45421a..e6035acb10 100644
---
a/common/workflow-operator/src/main/scala/org/apache/texera/amber/operator/source/fetcher/URLFetcherOpExec.scala
+++
b/common/workflow-operator/src/main/scala/org/apache/texera/amber/operator/source/fetcher/URLFetcherOpExec.scala
@@ -32,11 +32,9 @@ class URLFetcherOpExec(descString: String) extends
SourceOperatorExecutor {
override def produceTuple(): Iterator[TupleLike] = {
val urlObj = new URL(desc.url)
- val input = getInputStreamFromURL(urlObj)
- val contentInputStream = input match {
- case Some(value) => value
- case None => IOUtils.toInputStream(s"Fetch failed for URL:
$desc.url", "UTF-8")
- }
+ val contentInputStream = getInputStreamFromURL(urlObj).getOrElse(
+ IOUtils.toInputStream(s"Fetch failed for URL: ${desc.url}", "UTF-8")
+ )
Iterator(if (desc.decodingMethod == DecodingMethod.UTF_8) {
TupleLike(IOUtils.toString(contentInputStream, "UTF-8"))
} else {
diff --git
a/common/workflow-operator/src/test/scala/org/apache/texera/amber/operator/source/fetcher/URLFetcherOpExecSpec.scala
b/common/workflow-operator/src/test/scala/org/apache/texera/amber/operator/source/fetcher/URLFetcherOpExecSpec.scala
index 47770cbae8..a1a3967d65 100644
---
a/common/workflow-operator/src/test/scala/org/apache/texera/amber/operator/source/fetcher/URLFetcherOpExecSpec.scala
+++
b/common/workflow-operator/src/test/scala/org/apache/texera/amber/operator/source/fetcher/URLFetcherOpExecSpec.scala
@@ -44,4 +44,27 @@ class URLFetcherOpExecSpec extends AnyFlatSpec with
BeforeAndAfter {
assert(!iterator.hasNext)
}
+ // On a failed fetch the fallback message must interpolate `desc.url` itself,
+ // not the descriptor's reflectionToString dump. A file:// URL to a
nonexistent
+ // path makes getInputStreamFromURL return None deterministically and
offline,
+ // so the failure branch is exercised without depending on external
connectivity.
+ it should "report only the URL, not the operator descriptor, when the fetch
fails" in {
+ val missingUrl =
+ java.nio.file.Files
+ .createTempDirectory("texera-urlfetcher-regression-")
+ .resolve("missing")
+ .toUri
+ .toString
+ opDesc.url = missingUrl
+ opDesc.decodingMethod = DecodingMethod.UTF_8
+ val fetcherOpExec = new
URLFetcherOpExec(objectMapper.writeValueAsString(opDesc))
+ val content =
fetcherOpExec.produceTuple().next().getFields.toList.head.asInstanceOf[String]
+
+ assert(content == s"Fetch failed for URL: ${opDesc.url}")
+ // Guard against the pre-fix `$desc.url` behavior, which leaked the whole
+ // descriptor dump (class name + internal fields) into the message.
+ assert(!content.contains("URLFetcherOpDesc"))
+ assert(!content.contains("operatorId"))
+ }
+
}