mengw15 commented on code in PR #6853:
URL: https://github.com/apache/texera/pull/6853#discussion_r3649679486
##########
computing-unit-managing-service/src/main/scala/org/apache/texera/service/util/ComputingUnitHelpers.scala:
##########
@@ -19,11 +19,41 @@
package org.apache.texera.service.util
import org.apache.texera.dao.jooq.generated.enums.WorkflowComputingUnitTypeEnum
+import org.apache.texera.dao.jooq.generated.tables.daos.{UserDao,
WorkflowComputingUnitDao}
import org.apache.texera.dao.jooq.generated.tables.pojos.WorkflowComputingUnit
-import
org.apache.texera.service.resource.ComputingUnitManagingResource.WorkflowComputingUnitMetrics
+import org.apache.texera.service.resource.ComputingUnitManagingResource.{
+ DashboardWorkflowComputingUnit,
+ WorkflowComputingUnitMetrics
+}
import
org.apache.texera.service.resource.ComputingUnitState.{ComputingUnitState,
Pending, Running}
+import org.jooq.EnumType
+
+import java.sql.Timestamp
+import scala.jdk.CollectionConverters.{CollectionHasAsScala, SeqHasAsJava}
object ComputingUnitHelpers {
+
+ /**
+ * Owner (avatar, name) keyed by uid, resolved in one query. Blank values
collapse to `null`;
+ * empty `uids` returns empty without querying.
+ */
+ def resolveOwnerInfo(
+ userDao: UserDao,
+ uids: Seq[Integer]
+ ): Map[Integer, (String, String)] = {
+ if (uids.isEmpty) Map.empty
+ else
+ userDao
+ .fetchByUid(uids: _*)
+ .asScala
+ .map { u =>
+ val avatar = Option(u.getGoogleAvatar).filter(_.nonEmpty).orNull
+ val name = Option(u.getName).filter(_.nonEmpty).orNull
+ u.getUid -> (avatar, name)
+ }
+ .toMap
+ }
+
def getComputingUnitStatus(unit: WorkflowComputingUnit): ComputingUnitState
= {
Review Comment:
Optional / pre-existing: this single overload NPEs on a pod that has no
status yet (`_.getStatus.getPhase`), which `getComputingUnitInfo` can hit; the
bulk `getAllPodPhases` already guards it (`Option(pod.getStatus)...`). Worth
aligning while both live here. Not blocking.
##########
computing-unit-managing-service/src/main/scala/org/apache/texera/service/util/KubernetesClient.scala:
##########
@@ -20,18 +20,23 @@
package org.apache.texera.service.util
import io.fabric8.kubernetes.api.model._
-import io.fabric8.kubernetes.api.model.metrics.v1beta1.PodMetricsList
+import io.fabric8.kubernetes.api.model.metrics.v1beta1.PodMetrics
import io.fabric8.kubernetes.client.KubernetesClientBuilder
import org.apache.texera.common.config.KubernetesConfig
import scala.jdk.CollectionConverters._
object KubernetesClient {
- // Initialize the Kubernetes client
- private val client: io.fabric8.kubernetes.client.KubernetesClient =
+ private var client: io.fabric8.kubernetes.client.KubernetesClient =
new KubernetesClientBuilder().build()
private val namespace: String = KubernetesConfig.computeUnitPoolNamespace
+
+ /** Test-only seam to swap in a stubbed client (exercises the wrappers
without a live cluster). */
+ private[util] def setClientForTesting(
Review Comment:
Turning the production `client` into a mutable `var` just to stub it in
tests leaves a reassignable global whose isolation rests entirely on
`parallelExecution := false` + the `afterAll` restore — one parallel suite or
another client-touching test and the mock leaks. And it mostly covers fabric8
passthrough (`getPodByName` / `podExists`) via heavy fluent-chain mocking; the
logic worth pinning (status/metrics mapping, the `podPhasesFor` /
`podMetricsFor` guard) is already covered by the pure helpers in
`ComputingUnitHelpersSpec` without the global. Prefer injecting the client so
tests stub it without a prod `var`; if that's too big here, drop the wrapper
tests that need the seam.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]