-
Notifications
You must be signed in to change notification settings - Fork 301
[AutoSparkUT] Fix GPU missing-file recovery guidance [reduced-it] [fast-ut] [databricks] #15835
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 1 commit
07c1035
234f8dc
98650a4
c1e1a06
ad6d7a5
844a13f
3118411
43d7940
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -16,6 +16,9 @@ | |
|
|
||
| package com.nvidia.spark.rapids.shims | ||
|
|
||
| import java.io.FileNotFoundException | ||
| import java.util.concurrent.ExecutionException | ||
|
|
||
| import com.nvidia.spark.rapids.{FileSystemBytesReadTracker, MetricsBatchIterator, PartitionIterator} | ||
| import com.nvidia.spark.rapids.ScalableTaskCompletion.onTaskCompletion | ||
|
|
||
|
|
@@ -33,7 +36,8 @@ import org.apache.spark.sql.vectorized.ColumnarBatch | |
| class GpuDataSourceRDD( | ||
| sc: SparkContext, | ||
| @transient private val inputPartitions: Seq[Seq[InputPartition]], | ||
| partitionReaderFactory: PartitionReaderFactory | ||
| partitionReaderFactory: PartitionReaderFactory, | ||
| includeRefreshHint: Boolean = false | ||
| ) extends RDD[InternalRow](sc, Nil) { | ||
| import GpuDataSourceRDD.GpuDataSourceRDDPartition | ||
|
|
||
|
|
@@ -60,12 +64,21 @@ class GpuDataSourceRDD( | |
| private var currentIter: Option[Iterator[Object]] = None | ||
| private var currentIndex: Int = 0 | ||
|
|
||
| override def hasNext: Boolean = { | ||
| override def hasNext: Boolean = try { | ||
| val result = currentIter.exists(_.hasNext) || advanceToNextIter() | ||
| if (!result) { | ||
| bytesReadTracker.update() | ||
| } | ||
| result | ||
| } catch { | ||
| case e: FileNotFoundException => | ||
| throw GpuDataSourceRDD.withRecoveryHint(e, includeRefreshHint) | ||
| case e: ExecutionException => | ||
| e.getCause match { | ||
| case cause: FileNotFoundException => | ||
| throw GpuDataSourceRDD.withRecoveryHint(cause, includeRefreshHint) | ||
| case _ => throw e | ||
| } | ||
| } | ||
|
|
||
| override def next(): Object = { | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Updated. |
||
|
|
@@ -112,14 +125,43 @@ class GpuDataSourceRDD( | |
| } | ||
|
|
||
| object GpuDataSourceRDD { | ||
| private val RECREATE_HINT = "recreating the Dataset/DataFrame involved" | ||
| private val REFRESH_HINT = "REFRESH TABLE" | ||
|
|
||
| private def withRecoveryHint( | ||
| e: FileNotFoundException, | ||
| includeRefreshHint: Boolean): FileNotFoundException = { | ||
| val message = Option(e.getMessage).getOrElse(e.toString) | ||
| if (message.contains(RECREATE_HINT) && | ||
| (!includeRefreshHint || message.contains(REFRESH_HINT))) { | ||
| e | ||
| } else { | ||
| val recoveryHint = if (includeRefreshHint) { | ||
| "It is possible the underlying files have been updated. " + | ||
| "You can explicitly invalidate the cache in Spark by " + | ||
| "running 'REFRESH TABLE tableName' command in SQL or " + | ||
| "by recreating the Dataset/DataFrame involved." | ||
| } else { | ||
| "It is possible the underlying files have been updated. " + | ||
| "You can explicitly invalidate the cache in Spark by " + | ||
| "recreating the Dataset/DataFrame involved." | ||
| } | ||
| val enrichedException = new FileNotFoundException(s"$message\n$recoveryHint") | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could we make this translation version-aware before merging? This source is shared by every supported Spark build, but starting with Spark 4.0 the CPU file readers translate missing files through This branch always returns a plain
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As it's a SparkUT fix, I'm fine with doing it in a follow-up.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed. I’ll keep this SparkUT-focused PR scoped to Spark 3.x recovery guidance and handle Spark 4.x structured-error parity separately.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok, please file an issue to track if so.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Updated. |
||
| enrichedException.initCause(e) | ||
| enrichedException | ||
| } | ||
| } | ||
|
|
||
| private case class GpuDataSourceRDDPartition( | ||
| override val index: Int, | ||
| inputPartitions: Seq[InputPartition]) extends Partition | ||
|
|
||
| def apply( | ||
| sc: SparkContext, | ||
| inputPartitions: Seq[InputPartition], | ||
| partitionReaderFactory: PartitionReaderFactory): GpuDataSourceRDD = { | ||
| new GpuDataSourceRDD(sc, inputPartitions.map(Seq(_)), partitionReaderFactory) | ||
| partitionReaderFactory: PartitionReaderFactory, | ||
| includeRefreshHint: Boolean = false): GpuDataSourceRDD = { | ||
| new GpuDataSourceRDD( | ||
| sc, inputPartitions.map(Seq(_)), partitionReaderFactory, includeRefreshHint) | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.