Skip to content

Iceberg scan fails with a hard-wired 10s OpenDAL io_timeout that cannot be configured #6124

Description

@comphead

Describe the bug

A native Iceberg scan fails on a hard-wired 10 second per-IO timeout that nothing in Comet can configure:

org.apache.comet.CometNativeException: Iceberg scan error: Unexpected => Failed to read a Parquet file,
  source: External: Unexpected => Failure in doing io operation,
  source: Unexpected (persistent) at read, context: { timeout: 10 } => io operation timeout reached

The 10 is OpenDAL's default io_timeout. iceberg-storage-opendal applies TimeoutLayer::new() to every FileIO operator with no way to override it:

https://github.com/apache/iceberg-rust/blob/665c64e48e8d33797ecb1a421f327edd9b024879/crates/storage/opendal/src/lib.rs#L394

It bounds one ReadStream::read() chunk, not the whole file, so this is not a large-file problem. The RetryLayer outside it re-sends the same request, so a range that cannot fit in 10s fails identically on all four attempts and surfaces as persistent.

Comet cannot work around it: create_operator and the S3 config parsers are pub(crate), and iceberg::io::Storage is opaque, so BlobHostPromotingS3StorageFactory receives an already-layered Arc<dyn Storage>. Layers stack rather than replace, so adding a longer one on the outside does not help.

Expected behavior

The per-IO timeout should be tunable rather than failing the job.

Additional context

Fix proposed upstream: apache/iceberg-rust#3263, which adds client.io-timeout-ms and hands it to TimeoutLayer::with_io_timeout. Unset keeps the 10s default. Tracked by apache/iceberg-rust#2977; #3179 covers only the write path.

Once it merges, the Comet side is small because "client." is already in STORAGE_PROPERTY_PREFIXES (native/core/src/execution/operators/iceberg_common.rs:39):

  • Bump the pinned rev at native/Cargo.toml:67-68. No native change needed.
  • Add a CometConf entry (.timeConf(TimeUnit.MILLISECONDS)) and inject it at CometScanRule.scala:590 and CometIcebergNativeWrite.scala:687. Both read SQLConf at planning time, so unlike the fs.comet.* Hadoop keys this one would honor a runtime spark.conf.set.

Worth ruling out first, unverified for this report: TimeoutLayer measures wall clock, and Comet shares one tokio runtime per executor sized to spark.executor.cores (jni_api.rs:288-296). CPU-bound shuffle work on the same workers can leave an IO future unpolled past 10s on a healthy connection. Raising COMET_WORKER_THREADS tests that without a code change.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:Icebergarea:scanParquet scan / data readingbugSomething isn't workingpriority:mediumFunctional bugs, performance regressions, broken features

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions