This is an automated email from the ASF dual-hosted git repository.
sarutak pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/spark.git
The following commit(s) were added to refs/heads/master by this push:
new a6dddaebdc16 [SPARK-57894][SPARK-57895][CORE][K8S][DOC][FOLLOWUP] Add
documentation comments and `@volatile` fix for credential delivery
a6dddaebdc16 is described below
commit a6dddaebdc16b7bc9d362cdb5525a1bdeea312ea
Author: Kousuke Saruta <[email protected]>
AuthorDate: Mon Aug 10 14:56:47 2026 +0900
[SPARK-57894][SPARK-57895][CORE][K8S][DOC][FOLLOWUP] Add documentation
comments and `@volatile` fix for credential delivery
### What changes were proposed in this pull request?
Follow-up to #57675 addressing non-blocking review comments.
1. **Document missed-update window for late-registering executors**: Added
comments explaining the narrow window where a renewal broadcast (vN+1) could
arrive between an executor's `SparkAppConfig` reply (vN) and its registration
in `executorDataMap`, and noting that the `TaskDescription` path covers this
case.
2. **Document why initial credential application uses `set()` instead of
`updateIfNewer()`**: The store is guaranteed null at executor startup (before
any RPC or task is received), so the version guard comparison is unnecessary.
3. **Add `volatile` to `MockExecutorRpcEndpointRef` test fields**:
`decommissionReceived` and `receivedUserCredentials` are written by the RPC
dispatcher thread and read by the test thread inside `eventually`, so
visibility must be guaranteed.
4. **Clarify TaskDescription overhead comment**: Qualified as "in-memory
overhead at any instant" to distinguish from cumulative network transfer cost.
### Why are the changes needed?
These address non-blocking review feedback on #57675 to improve code
documentation and test correctness.
### Does this PR introduce _any_ user-facing change?
No.
### How was this patch tested?
GA.
### Was this patch authored or co-authored using generative AI tooling?
Kiro CLI / Claude
Closes #57877 from sarutak/oidc-propagation/subtask5-followup-nits.
Authored-by: Kousuke Saruta <[email protected]>
Signed-off-by: Kousuke Saruta <[email protected]>
---
.../org/apache/spark/executor/CoarseGrainedExecutorBackend.scala | 6 ++++++
.../src/main/scala/org/apache/spark/scheduler/TaskDescription.scala | 2 +-
.../apache/spark/scheduler/CoarseGrainedSchedulerBackendSuite.scala | 4 ++--
.../spark/scheduler/cluster/k8s/KubernetesExecutorBackend.scala | 6 ++++++
4 files changed, 15 insertions(+), 3 deletions(-)
diff --git
a/core/src/main/scala/org/apache/spark/executor/CoarseGrainedExecutorBackend.scala
b/core/src/main/scala/org/apache/spark/executor/CoarseGrainedExecutorBackend.scala
index 7429774cec60..375682383b1f 100644
---
a/core/src/main/scala/org/apache/spark/executor/CoarseGrainedExecutorBackend.scala
+++
b/core/src/main/scala/org/apache/spark/executor/CoarseGrainedExecutorBackend.scala
@@ -513,6 +513,12 @@ private[spark] object CoarseGrainedExecutorBackend extends
Logging {
arguments.hostname, arguments.cores, cfg.ioEncryptionKey, isLocal =
false)
// Apply initial user credentials to the executor credential store.
+ // Uses unconditional set() rather than updateIfNewer() because the
store is guaranteed
+ // null at this point (executor startup, before any RPC or task is
received).
+ // Note: there is a narrow window where a renewal broadcast (vN+1) could
arrive between
+ // the SparkAppConfig reply (vN) and executor registration in
executorDataMap, leaving
+ // this executor on vN until vN+2. The TaskDescription path covers this
case since
+ // every dispatched task carries the latest credentials.
cfg.userCredentials.foreach { case (version, credentials) =>
env.userCredentials.set(VersionedCredentials(version, credentials))
}
diff --git
a/core/src/main/scala/org/apache/spark/scheduler/TaskDescription.scala
b/core/src/main/scala/org/apache/spark/scheduler/TaskDescription.scala
index 42b0d33d724c..db67b69fd9d7 100644
--- a/core/src/main/scala/org/apache/spark/scheduler/TaskDescription.scala
+++ b/core/src/main/scala/org/apache/spark/scheduler/TaskDescription.scala
@@ -69,7 +69,7 @@ private[spark] class TaskDescription(
// This is acceptable because OIDC credentials are short-lived (minutes)
unlike Hadoop
// delegation tokens (hours/days), making the race between RPC broadcast
and task dispatch
// a practical concern. For short-task-heavy workloads, the overhead is
bounded by
- // credential size x tasks-in-flight (not total task count).
+ // credential size x tasks-in-flight at any instant (not total task count).
val userCredentials: Option[(Long, Array[Byte])],
val serializedTask: ByteBuffer) {
diff --git
a/core/src/test/scala/org/apache/spark/scheduler/CoarseGrainedSchedulerBackendSuite.scala
b/core/src/test/scala/org/apache/spark/scheduler/CoarseGrainedSchedulerBackendSuite.scala
index 462daa046835..10eb884619b5 100644
---
a/core/src/test/scala/org/apache/spark/scheduler/CoarseGrainedSchedulerBackendSuite.scala
+++
b/core/src/test/scala/org/apache/spark/scheduler/CoarseGrainedSchedulerBackendSuite.scala
@@ -803,8 +803,8 @@ private[spark] class MockExecutorRpcEndpointRef(conf:
SparkConf) extends RpcEndp
import scala.concurrent.ExecutionContext.Implicits.global
// scalastyle:on executioncontextglobal
- var decommissionReceived = false
- var receivedUserCredentials: Option[(Long, Array[Byte])] = None
+ @volatile var decommissionReceived = false
+ @volatile var receivedUserCredentials: Option[(Long, Array[Byte])] = None
override def address: RpcAddress = null
override def name: String = "executor"
diff --git
a/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/scheduler/cluster/k8s/KubernetesExecutorBackend.scala
b/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/scheduler/cluster/k8s/KubernetesExecutorBackend.scala
index 5b8a30fdab1c..385bc82a35e2 100644
---
a/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/scheduler/cluster/k8s/KubernetesExecutorBackend.scala
+++
b/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/scheduler/cluster/k8s/KubernetesExecutorBackend.scala
@@ -129,6 +129,12 @@ private[spark] object KubernetesExecutorBackend extends
Logging {
arguments.hostname, arguments.cores, cfg.ioEncryptionKey, isLocal =
false)
// Apply initial user credentials to the executor credential store.
+ // Uses unconditional set() rather than updateIfNewer() because the
store is guaranteed
+ // null at this point (executor startup, before any RPC or task is
received).
+ // Note: there is a narrow window where a renewal broadcast (vN+1) could
arrive between
+ // the SparkAppConfig reply (vN) and executor registration in
executorDataMap, leaving
+ // this executor on vN until vN+2. The TaskDescription path covers this
case since
+ // every dispatched task carries the latest credentials.
cfg.userCredentials.foreach { case (version, credentials) =>
env.userCredentials.set(VersionedCredentials(version, credentials))
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]