Fix multiple relation batch update (#22352)

* Fix multiple relationship bulk add

* Remove unused code
This commit is contained in:
Sriharsha Chintalapani 2025-07-14 15:01:49 -07:00 committed by GitHub
parent b48a02d94e
commit 46a35d075c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 75 additions and 22 deletions

View File

@ -4222,30 +4222,45 @@ public abstract class EntityRepository<T extends EntityInterface> {
// Batch add new relationships
if (!added.isEmpty()) {
// Create forward relationships
List<UUID> addedIds =
added.stream().map(EntityReference::getId).collect(Collectors.toList());
daoCollection
.relationshipDAO()
.bulkInsertToRelationship(
fromId, addedIds, fromEntityType, toEntityType, relationshipType.ordinal());
if (bidirectional) {
// Create reverse relationships using bulkInsertTo for true batch operation
List<CollectionDAO.EntityRelationshipObject> reverseRelationships =
added.stream()
.map(
ref ->
CollectionDAO.EntityRelationshipObject.builder()
.fromId(ref.getId().toString())
.toId(fromId.toString())
.fromEntity(ref.getType())
.toEntity(fromEntityType)
.relation(relationshipType.ordinal())
.build())
.collect(Collectors.toList());
// For bidirectional relationships, apply the optimization where smaller UUID is always
// fromId
List<CollectionDAO.EntityRelationshipObject> optimizedRelationships = new ArrayList<>();
for (EntityReference ref : added) {
UUID id1 = fromId;
UUID id2 = ref.getId();
String entity1 = fromEntityType;
String entity2 = ref.getType();
daoCollection.relationshipDAO().bulkInsertTo(reverseRelationships);
// Ensure smaller UUID is always fromId for bidirectional relationships
if (id1.compareTo(id2) > 0) {
// Swap the IDs and entities
UUID tempId = id1;
id1 = id2;
id2 = tempId;
String tempEntity = entity1;
entity1 = entity2;
entity2 = tempEntity;
}
optimizedRelationships.add(
CollectionDAO.EntityRelationshipObject.builder()
.fromId(id1.toString())
.toId(id2.toString())
.fromEntity(entity1)
.toEntity(entity2)
.relation(relationshipType.ordinal())
.build());
}
daoCollection.relationshipDAO().bulkInsertTo(optimizedRelationships);
} else {
// For non-bidirectional relationships, just create forward relationships
List<UUID> addedIds =
added.stream().map(EntityReference::getId).collect(Collectors.toList());
daoCollection
.relationshipDAO()
.bulkInsertToRelationship(
fromId, addedIds, fromEntityType, toEntityType, relationshipType.ordinal());
}
}
if (!nullOrEmpty(updatedToRefs)) {

View File

@ -57,6 +57,43 @@ public class MetricResourceTest extends EntityResourceTest<Metric, CreateMetric>
Metric2 = createEntity(createMetric, ADMIN_AUTH_HEADERS);
}
@Test
void test_duplicateRelatedMetricsIssue() throws IOException {
CreateMetric createMetric1 = createRequest("test_metric_duplicate_1", "", "", null);
Metric metric1 = createEntity(createMetric1, ADMIN_AUTH_HEADERS);
CreateMetric createMetric2 = createRequest("test_metric_duplicate_2", "", "", null);
Metric metric2 = createEntity(createMetric2, ADMIN_AUTH_HEADERS);
Metric originalMetric2 = getMetric(metric2.getId(), "*", ADMIN_AUTH_HEADERS);
String origJson = JsonUtils.pojoToJson(originalMetric2);
originalMetric2.setRelatedMetrics(List.of(metric1.getEntityReference()));
patchEntity(originalMetric2.getId(), origJson, originalMetric2, ADMIN_AUTH_HEADERS);
Metric updatedMetric2 = getMetric(metric2.getId(), "relatedMetrics", ADMIN_AUTH_HEADERS);
Assertions.assertNotNull(updatedMetric2.getRelatedMetrics());
Assertions.assertEquals(
1,
updatedMetric2.getRelatedMetrics().size(),
"Expected only 1 related metric, but found "
+ updatedMetric2.getRelatedMetrics().size()
+ ". Related metrics: "
+ updatedMetric2.getRelatedMetrics());
Assertions.assertEquals(metric1.getId(), updatedMetric2.getRelatedMetrics().getFirst().getId());
// Also verify that metric1 now has metric2 as a related metric (bidirectional)
Metric updatedMetric1 = getMetric(metric1.getId(), "relatedMetrics", ADMIN_AUTH_HEADERS);
Assertions.assertNotNull(updatedMetric1.getRelatedMetrics());
Assertions.assertEquals(
1,
updatedMetric1.getRelatedMetrics().size(),
"Expected only 1 related metric for the reverse relationship, but found "
+ updatedMetric1.getRelatedMetrics().size());
Assertions.assertEquals(metric2.getId(), updatedMetric1.getRelatedMetrics().getFirst().getId());
}
@Test
void patch_MetricEntity() throws IOException {
// Create a new Metric with different fields
@ -177,6 +214,7 @@ public class MetricResourceTest extends EntityResourceTest<Metric, CreateMetric>
return entity;
}
@SuppressWarnings("unchecked")
@Override
public void assertFieldChange(String fieldName, Object expected, Object actual) {
if (expected != null && actual != null) {