This is an automated email from the ASF dual-hosted git repository.

jmclean pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/gravitino.git


The following commit(s) were added to refs/heads/main by this push:
     new fa805b0a44 [#10176] fix: update BuiltInJobTemplate identifier to use 
existing entity name (#10257)
fa805b0a44 is described below

commit fa805b0a447eeda13a74b0864a2da1e5d4bb3536
Author: ajw711 <[email protected]>
AuthorDate: Sat Mar 7 05:57:34 2026 +0900

    [#10176] fix: update BuiltInJobTemplate identifier to use existing entity 
name (#10257)
    
    ### What changes were proposed in this pull request?
    
    Changed `newTemplate.name()` to `existing.name()` in
    `BuiltInJobTemplateEventListener.updateBuiltInJobTemplate()`.
    
    ### Why are the changes needed?
    
    When updating a job template, `EntityStore` uses the logical identifier
    (`name`) to find and update the target record. The previous code
    incorrectly built the `NameIdentifier` using the incoming
    `newTemplate.name()`. Since the new name does not exist in the database
    yet, it caused a `NoSuchEntityException`. Using `existing.name()`
    ensures the system locks and updates the correct existing entity.
    
    Fix: #10176
    
    ### Does this PR introduce _any_ user-facing change?
    
    No.
    
    ### How was this patch tested?
    
    Ran the specific unit test locally and verified it passes:
    `./gradlew :core:test --tests
    "*testReconcileBuiltInJobTemplatesUpdateUsesExistingIdentifier*"`
    
    ---------
    
    Co-authored-by: jinwon <[email protected]>
---
 .../job/BuiltInJobTemplateEventListener.java       |  5 +++-
 .../job/TestBuiltInJobTemplateEventListener.java   | 35 ++++++++++++++++++++++
 2 files changed, 39 insertions(+), 1 deletion(-)

diff --git 
a/core/src/main/java/org/apache/gravitino/job/BuiltInJobTemplateEventListener.java
 
b/core/src/main/java/org/apache/gravitino/job/BuiltInJobTemplateEventListener.java
index a445aa13aa..11070fe2e2 100644
--- 
a/core/src/main/java/org/apache/gravitino/job/BuiltInJobTemplateEventListener.java
+++ 
b/core/src/main/java/org/apache/gravitino/job/BuiltInJobTemplateEventListener.java
@@ -310,7 +310,10 @@ public class BuiltInJobTemplateEventListener implements 
EventListenerPlugin {
 
   private void updateBuiltInJobTemplate(
       String metalake, JobTemplateEntity existing, JobTemplate newTemplate) {
-    NameIdentifier identifier = NameIdentifierUtil.ofJobTemplate(metalake, 
newTemplate.name());
+    // Use existing.name() (not newTemplate.name()) so the EntityStore can 
locate the
+    // already-persisted record. Using newTemplate.name() would cause 
NoSuchEntityException
+    // if the template is ever renamed between Gravitino versions. See #10176.
+    NameIdentifier identifier = NameIdentifierUtil.ofJobTemplate(metalake, 
existing.name());
 
     TreeLockUtils.doWithTreeLock(
         identifier,
diff --git 
a/core/src/test/java/org/apache/gravitino/job/TestBuiltInJobTemplateEventListener.java
 
b/core/src/test/java/org/apache/gravitino/job/TestBuiltInJobTemplateEventListener.java
index a02934c2c4..7b6a004c4c 100644
--- 
a/core/src/test/java/org/apache/gravitino/job/TestBuiltInJobTemplateEventListener.java
+++ 
b/core/src/test/java/org/apache/gravitino/job/TestBuiltInJobTemplateEventListener.java
@@ -486,6 +486,41 @@ public class TestBuiltInJobTemplateEventListener {
     listener.reconcileBuiltInJobTemplates(metalakeName, builtInTemplates);
   }
 
+  @Test
+  public void testReconcileBuiltInJobTemplatesUpdateUsesExistingIdentifier() 
throws IOException {
+    String metalakeName = "test_metalake";
+
+    JobTemplateEntity existingEntity = 
createJobTemplateEntity("builtin-existing", "v1");
+    entityStore.put(existingEntity, false);
+
+    ShellJobTemplate newTemplate =
+        ShellJobTemplate.builder()
+            .withName("builtin-existing")
+            .withComment("updated")
+            .withExecutable("/bin/echo")
+            .withCustomFields(Collections.singletonMap("version", "v2"))
+            .build();
+
+    Map<String, JobTemplate> builtInTemplates = new HashMap<>();
+    builtInTemplates.put(newTemplate.name(), newTemplate);
+
+    when(jobManager.listJobTemplates(metalakeName))
+        .thenReturn(Collections.singletonList(existingEntity));
+
+    Assertions.assertDoesNotThrow(
+        () -> listener.reconcileBuiltInJobTemplates(metalakeName, 
builtInTemplates));
+
+    JobTemplateEntity updated =
+        entityStore.get(
+            existingEntity.nameIdentifier(),
+            Entity.EntityType.JOB_TEMPLATE,
+            JobTemplateEntity.class);
+
+    Assertions.assertNotNull(updated);
+    Assertions.assertEquals("v2", 
updated.templateContent().customFields().get("version"));
+    Assertions.assertEquals("builtin-existing", updated.name());
+  }
+
   private void createMetalake(String name, boolean inUse) throws IOException {
     Map<String, String> props = new HashMap<>();
     props.put(PROPERTY_IN_USE, String.valueOf(inUse));

Reply via email to