pan3793 commented on code in PR #7709:
URL: https://github.com/apache/kyuubi/pull/7709#discussion_r3920506825


##########
kyuubi-server/src/main/scala/org/apache/kyuubi/server/metadata/jdbc/JDBCMetadataStore.scala:
##########
@@ -332,76 +332,97 @@ class JDBCMetadataStore(conf: KyuubiConf) extends 
MetadataStore with Logging {
 
   override def updateMetadata(metadata: Metadata): Unit = {
     val queryBuilder = new StringBuilder
-    val params = ListBuffer[Any]()
+    val updateFields = ListBuffer[(String, Any)]()
 
     queryBuilder.append(s"UPDATE $METADATA_TABLE")
-    val setClauses = ListBuffer[String]()
     Option(metadata.kyuubiInstance).foreach { _ =>
-      setClauses += "kyuubi_instance = ?"
-      params += metadata.kyuubiInstance
+      updateFields += (("kyuubi_instance", metadata.kyuubiInstance))
     }
     Option(metadata.state).foreach { _ =>
-      setClauses += "state = ?"
-      params += metadata.state
+      updateFields += (("state", metadata.state))
     }
     Option(metadata.requestConf).filter(_.nonEmpty).foreach { _ =>
-      setClauses += "request_conf =?"
-      params += valueAsString(metadata.requestConf)
+      updateFields += (("request_conf", valueAsString(metadata.requestConf)))
     }
     metadata.clusterManager.foreach { cm =>
-      setClauses += "cluster_manager = ?"
-      params += cm
+      updateFields += (("cluster_manager", cm))
     }
     if (metadata.endTime > 0) {
-      setClauses += "end_time = ?"
-      params += metadata.endTime
+      updateFields += (("end_time", metadata.endTime))
     }
     if (metadata.engineOpenTime > 0) {
-      setClauses += "engine_open_time = ?"
-      params += metadata.engineOpenTime
+      updateFields += (("engine_open_time", metadata.engineOpenTime))
     }
     Option(metadata.engineId).foreach { _ =>
-      setClauses += "engine_id = ?"
-      params += metadata.engineId
+      updateFields += (("engine_id", metadata.engineId))
     }
     Option(metadata.engineName).foreach { _ =>
-      setClauses += "engine_name = ?"
-      params += metadata.engineName
+      updateFields += (("engine_name", metadata.engineName))
     }
     Option(metadata.engineUrl).foreach { _ =>
-      setClauses += "engine_url = ?"
-      params += metadata.engineUrl
+      updateFields += (("engine_url", metadata.engineUrl))
     }
     Option(metadata.engineState).foreach { _ =>
-      setClauses += "engine_state = ?"
-      params += metadata.engineState
+      updateFields += (("engine_state", metadata.engineState))
     }
     metadata.engineError.foreach { error =>
-      setClauses += "engine_error = ?"
-      params += error
+      updateFields += (("engine_error", error))
     }
     if (metadata.peerInstanceClosed) {
-      setClauses += "peer_instance_closed = ?"
-      params += metadata.peerInstanceClosed
+      updateFields += (("peer_instance_closed", metadata.peerInstanceClosed))
     }
-    if (setClauses.nonEmpty) {
-      queryBuilder.append(setClauses.mkString(" SET ", ", ", ""))
+    if (updateFields.nonEmpty) {
+      queryBuilder.append(updateFields.map { case (column, _) =>
+        s"$column = ?"
+      }.mkString(" SET ", ", ", ""))
     }
     queryBuilder.append(" WHERE identifier = ?")
-    params += metadata.identifier
+    val params = updateFields.map(_._2) :+ metadata.identifier
 
     val query = queryBuilder.toString()
     JdbcUtils.withConnection { connection =>
       withUpdateCount(connection, query, params.toSeq: _*) { updateCount =>
         if (updateCount == 0) {
-          throw new KyuubiException(
-            s"Error updating metadata for ${metadata.identifier} by SQL: 
$query, " +
-              s"with params: ${params.mkString(", ")}")
+          verifyMetadataUpdatePostcondition(connection, metadata.identifier, 
updateFields.toSeq)
         }
       }
     }
   }
 
+  private def verifyMetadataUpdatePostcondition(

Review Comment:
   Since #7708 says the original cause of the zero update count is still under 
investigation, please log a `warn` here when the row already matches, e.g. 
"update for {} returned 0 but all requested values already match, treating as 
idempotent success". Otherwise this case becomes invisible, while the old 
behavior at least surfaced an exception.



##########
kyuubi-server/src/main/scala/org/apache/kyuubi/server/metadata/MetadataStore.scala:
##########
@@ -118,3 +119,17 @@ trait MetadataStore extends Closeable {
    */
   def cleanupKubernetesEngineInfoByAge(maxAge: Long, limit: Int): Int
 }
+
+sealed abstract private[metadata] class 
MetadataUpdatePostconditionException(message: String)
+  extends KyuubiException(message)
+
+private[metadata] class MetadataRowNotFoundException(identifier: String)
+  extends MetadataUpdatePostconditionException(
+    s"Metadata row $identifier was not found after an update returned 0")
+
+private[metadata] class MetadataUpdateMismatchException(

Review Comment:
   Nit: consider including expected vs actual values in the message, not just 
column names. When the discard is logged in `MetadataManager`, that makes the 
error actionable without reproducing the DB state.



-- 
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]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to