You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@atlas.apache.org by pi...@apache.org on 2026/10/27 10:26:35 UTC
(atlas) branch atlas-2.6 updated: ATLAS-5425:Implement getEntitiesWithTagChanges for RDBMS audit repository (#791)
This is an automated email from the ASF dual-hosted git repository.
pinal-shah pushed a commit to branch atlas-2.6
in repository https://gitbox.apache.org/repos/asf/atlas.git
The following commit(s) were added to refs/heads/atlas-2.6 by this push:
new cdc880b57b ATLAS-5425:Implement getEntitiesWithTagChanges for RDBMS audit repository (#791)
cdc880b57b is described below
commit cdc880b57b6cbf8ed06378b45753790bc3369dc4
Author: bhor-sanket <sa...@gmail.com>
AuthorDate: Tue Oct 27 15:52:57 2026 +0530
ATLAS-5425:Implement getEntitiesWithTagChanges for RDBMS audit repository (#791)
Co-authored-by: sanket.bhor <sa...@cloudera.com>
(cherry picked from commit e56cd028949ce05c6c76895957ea951fac896e41)
---
.../audit/rdbms/dao/DbEntityAuditDao.java | 14 ++++++
.../resources/META-INF/janus-jpa_named_queries.xml | 8 +++
.../audit/rdbms/RdbmsBasedAuditRepository.java | 15 +++++-
.../repository/audit/AuditRepositoryTestBase.java | 58 ++++++++++++++++++++++
4 files changed, 93 insertions(+), 2 deletions(-)
diff --git a/graphdb/janusgraph-rdbms/src/main/java/org/apache/atlas/repository/audit/rdbms/dao/DbEntityAuditDao.java b/graphdb/janusgraph-rdbms/src/main/java/org/apache/atlas/repository/audit/rdbms/dao/DbEntityAuditDao.java
index e6880344df..694abec732 100644
--- a/graphdb/janusgraph-rdbms/src/main/java/org/apache/atlas/repository/audit/rdbms/dao/DbEntityAuditDao.java
+++ b/graphdb/janusgraph-rdbms/src/main/java/org/apache/atlas/repository/audit/rdbms/dao/DbEntityAuditDao.java
@@ -100,6 +100,20 @@ public class DbEntityAuditDao extends BaseDao<DbEntityAudit> {
return orderByQuery.toString();
}
+ public List<String> getDistinctEntityIdsByActionPrefixAndTimeRange(String actionPrefix, long fromTimestamp, long toTimestamp) {
+ try {
+ return em.createNamedQuery("DbEntityAudit.getDistinctEntityIdsByActionPrefixAndTimeRange", String.class)
+ .setParameter("actionPrefix", actionPrefix)
+ .setParameter("fromTimestamp", fromTimestamp)
+ .setParameter("toTimestamp", toTimestamp)
+ .getResultList();
+ } catch (NoResultException excp) {
+ // ignore
+ }
+
+ return Collections.emptyList();
+ }
+
public List<DbEntityAudit> getLatestAuditsByEntityIdAction(String entityId, String action, List<String> filterActions) {
try {
StringBuilder query = new StringBuilder("SELECT e FROM DbEntityAudit e WHERE e.entityId = :entityId");
diff --git a/graphdb/janusgraph-rdbms/src/main/resources/META-INF/janus-jpa_named_queries.xml b/graphdb/janusgraph-rdbms/src/main/resources/META-INF/janus-jpa_named_queries.xml
index a0258f5ba3..caacaff14b 100644
--- a/graphdb/janusgraph-rdbms/src/main/resources/META-INF/janus-jpa_named_queries.xml
+++ b/graphdb/janusgraph-rdbms/src/main/resources/META-INF/janus-jpa_named_queries.xml
@@ -32,6 +32,14 @@
</query>
</named-query>
+ <named-query name="DbEntityAudit.getDistinctEntityIdsByActionPrefixAndTimeRange">
+ <query>SELECT DISTINCT obj.entityId FROM DbEntityAudit obj
+ WHERE obj.action LIKE :actionPrefix
+ AND obj.eventTime >= :fromTimestamp
+ AND obj.eventTime < :toTimestamp
+ </query>
+ </named-query>
+
<named-query name="JanusStore.getIdByName">
<query>SELECT s.id FROM JanusStore s WHERE s.name = :name</query>
</named-query>
diff --git a/repository/src/main/java/org/apache/atlas/repository/audit/rdbms/RdbmsBasedAuditRepository.java b/repository/src/main/java/org/apache/atlas/repository/audit/rdbms/RdbmsBasedAuditRepository.java
index 7012a99798..e620485986 100644
--- a/repository/src/main/java/org/apache/atlas/repository/audit/rdbms/RdbmsBasedAuditRepository.java
+++ b/repository/src/main/java/org/apache/atlas/repository/audit/rdbms/RdbmsBasedAuditRepository.java
@@ -45,6 +45,7 @@ import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
+import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@@ -120,8 +121,18 @@ public class RdbmsBasedAuditRepository extends AbstractStorageBasedAuditReposito
@Override
public Set<String> getEntitiesWithTagChanges(long fromTimestamp, long toTimestamp) throws AtlasBaseException {
- // TODO:
- return Collections.emptySet();
+ LOG.debug("Listing entities with tag changes for fromTimestamp {}, toTimestamp {}", fromTimestamp, toTimestamp);
+
+ try (RdbmsTransaction trx = new RdbmsTransaction()) {
+ DbEntityAuditDao dao = new DbEntityAuditDao(trx.getEntityManager());
+
+ List<String> entityIds = dao.getDistinctEntityIdsByActionPrefixAndTimeRange(
+ "CLASSIFICATION_%", fromTimestamp, toTimestamp);
+
+ return new HashSet<>(entityIds);
+ } catch (Exception excp) {
+ throw new AtlasBaseException("Error while retrieving entities with tag changes", excp);
+ }
}
@Override
diff --git a/repository/src/test/java/org/apache/atlas/repository/audit/AuditRepositoryTestBase.java b/repository/src/test/java/org/apache/atlas/repository/audit/AuditRepositoryTestBase.java
index 82f5862cc4..3604e906df 100644
--- a/repository/src/test/java/org/apache/atlas/repository/audit/AuditRepositoryTestBase.java
+++ b/repository/src/test/java/org/apache/atlas/repository/audit/AuditRepositoryTestBase.java
@@ -32,6 +32,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import java.util.stream.Collectors;
import static org.testng.Assert.assertEquals;
@@ -245,6 +246,63 @@ public class AuditRepositoryTestBase {
assertEquals(latestEvent, remainingEventsByTTL.get(0));
}
+ @Test
+ public void testGetEntitiesWithTagChanges() throws Exception {
+ String entityId1 = "tagChangeEntity1-" + rand();
+ String entityId2 = "tagChangeEntity2-" + rand();
+ String entityId3 = "tagChangeEntity3-" + rand();
+ AtlasEntity entity = new AtlasEntity(rand());
+ long ts = System.currentTimeMillis();
+
+ eventRepository.putEventsV2(new EntityAuditEventV2(entityId1, ts + 1, "user1",
+ EntityAuditEventV2.EntityAuditActionV2.CLASSIFICATION_ADD, "added PII", entity));
+ eventRepository.putEventsV2(new EntityAuditEventV2(entityId2, ts + 2, "user1",
+ EntityAuditEventV2.EntityAuditActionV2.CLASSIFICATION_DELETE, "deleted PII", entity));
+ eventRepository.putEventsV2(new EntityAuditEventV2(entityId3, ts + 3, "user1",
+ EntityAuditEventV2.EntityAuditActionV2.CLASSIFICATION_UPDATE, "updated PII", entity));
+
+ Set<String> result = eventRepository.getEntitiesWithTagChanges(ts, ts + 10);
+
+ assertNotNull(result);
+ assertTrue(result.contains(entityId1), "Expected CLASSIFICATION_ADD entity in result");
+ assertTrue(result.contains(entityId2), "Expected CLASSIFICATION_DELETE entity in result");
+ assertTrue(result.contains(entityId3), "Expected CLASSIFICATION_UPDATE entity in result");
+ }
+
+ @Test
+ public void testGetEntitiesWithTagChanges_emptyForNoMatchingTimeRange() throws Exception {
+ String entityId = "tagChangeNoMatch-" + rand();
+ AtlasEntity entity = new AtlasEntity(rand());
+ long ts = System.currentTimeMillis();
+
+ eventRepository.putEventsV2(new EntityAuditEventV2(entityId, ts + 100, "user1",
+ EntityAuditEventV2.EntityAuditActionV2.CLASSIFICATION_ADD, "added PII", entity));
+
+ Set<String> result = eventRepository.getEntitiesWithTagChanges(ts, ts + 10);
+
+ assertNotNull(result);
+ assertFalse(result.contains(entityId), "Entity outside time range should not be in result");
+ }
+
+ @Test
+ public void testGetEntitiesWithTagChanges_deduplicatesEntities() throws Exception {
+ String entityId = "tagChangeDuplicate-" + rand();
+ AtlasEntity entity = new AtlasEntity(rand());
+ long ts = System.currentTimeMillis();
+
+ eventRepository.putEventsV2(new EntityAuditEventV2(entityId, ts + 1, "user1",
+ EntityAuditEventV2.EntityAuditActionV2.CLASSIFICATION_ADD, "added PII", entity));
+ eventRepository.putEventsV2(new EntityAuditEventV2(entityId, ts + 2, "user1",
+ EntityAuditEventV2.EntityAuditActionV2.CLASSIFICATION_UPDATE, "updated PII", entity));
+
+ Set<String> result = eventRepository.getEntitiesWithTagChanges(ts, ts + 10);
+
+ assertNotNull(result);
+ assertTrue(result.contains(entityId));
+ long count = result.stream().filter(id -> id.equals(entityId)).count();
+ assertEquals(count, 1, "Entity should appear only once in the result set");
+ }
+
protected void assertEventV1Equals(EntityAuditEvent actual, EntityAuditEvent expected) {
if (expected != null) {
assertNotNull(actual);