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));