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

asf-gitbox-commits pushed a commit to branch atlas-4464
in repository https://gitbox.apache.org/repos/asf/atlas.git


The following commit(s) were added to refs/heads/atlas-4464 by this push:
     new fd1743d57 ATLAS-4464: Concurrent ingest implementation - fixing test 
cases
fd1743d57 is described below

commit fd1743d57261ca5a819cb96db188e11919b844e2
Author: Radhika Kundam <[email protected]>
AuthorDate: Thu Jun 4 16:35:28 2026 -0700

    ATLAS-4464: Concurrent ingest implementation - fixing test cases
---
 .../notification/NotificationHookConsumerTest.java | 338 ++++++++++++---------
 1 file changed, 198 insertions(+), 140 deletions(-)

diff --git 
a/webapp/src/test/java/org/apache/atlas/notification/NotificationHookConsumerTest.java
 
b/webapp/src/test/java/org/apache/atlas/notification/NotificationHookConsumerTest.java
index b3653aa9f..4bbfe4109 100644
--- 
a/webapp/src/test/java/org/apache/atlas/notification/NotificationHookConsumerTest.java
+++ 
b/webapp/src/test/java/org/apache/atlas/notification/NotificationHookConsumerTest.java
@@ -51,6 +51,7 @@ import org.apache.atlas.type.AtlasEntityType;
 import org.apache.atlas.type.AtlasStructType;
 import org.apache.atlas.type.AtlasType;
 import org.apache.atlas.type.AtlasTypeRegistry;
+import org.apache.atlas.util.AdaptiveWaiter;
 import org.apache.atlas.util.AtlasMetricsUtil;
 import org.apache.atlas.v1.model.instance.Referenceable;
 import org.apache.atlas.v1.model.notification.HookNotificationV1;
@@ -65,6 +66,7 @@ import org.mockito.MockedStatic;
 import org.mockito.MockitoAnnotations;
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
+import org.slf4j.LoggerFactory;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
@@ -202,17 +204,23 @@ public class NotificationHookConsumerTest {
     }
 
     @Test
-    public void testCommitIsNotCalledEvenWhenMessageProcessingFails() throws 
AtlasServiceException, AtlasException, AtlasBaseException {
+    public void testCommitIsNotCalledEvenWhenMessageProcessingFails() throws 
Exception {
+        Configuration config = buildFailedMsgCacheConfig(10);
+        when(config.getInt(NotificationHookConsumer.CONSUMER_RETRIES_PROPERTY, 
3)).thenReturn(1);
+
         NotificationHookConsumer notificationHookConsumer = new 
NotificationHookConsumer(notificationInterface, atlasEntityStore, serviceState, 
instanceConverter, typeRegistry, metricsUtil, null, asyncImporter);
         NotificationConsumer consumer = mock(NotificationConsumer.class);
-        NotificationHookConsumer.HookConsumer hookConsumer = 
notificationHookConsumer.new HookConsumer(consumer);
+        NotificationHookConsumer.HookConsumer hookConsumer = 
(NotificationHookConsumer.HookConsumer) createHookConsumerWithEntityProcessor(
+                notificationHookConsumer, consumer, 
createEntityProcessor(config));
+
         EntityCreateRequest message = new EntityCreateRequest("user", 
Collections.singletonList(mock(Referenceable.class)));
 
         when(atlasEntityStore.createOrUpdate(any(EntityStream.class), 
anyBoolean())).thenThrow(new RuntimeException("Simulating exception in 
processing message"));
 
         hookConsumer.handleMessage(new AtlasKafkaMessage(message, -1, 
KafkaNotification.ATLAS_HOOK_TOPIC, -1));
 
-        verifyZeroInteractions(consumer);
+        // After max retries, the offset is committed so the consumer can move 
past the failed message
+        verify(consumer, times(1)).commit(any(TopicPartition.class), 
anyLong());
     }
 
     @Test
@@ -765,11 +773,13 @@ public class NotificationHookConsumerTest {
 
     @Test
     public void testHookConsumerCreateOrUpdateWithBatching() throws Exception {
-        NotificationHookConsumer consumer = createTestConsumerWithBatching(5); 
// batch size of 5
+        Configuration batchConfig = buildBatchingConfig(5);
+        NotificationHookConsumer consumer = createTestConsumer();
         NotificationConsumer<HookNotification> notificationConsumer = 
mock(NotificationConsumer.class);
-        Object hookConsumer = createHookConsumer(consumer, 
notificationConsumer);
+        Object hookConsumer = createHookConsumerWithEntityProcessor(consumer, 
notificationConsumer, createEntityProcessor(batchConfig));
 
-        Method createOrUpdateMethod = 
hookConsumer.getClass().getDeclaredMethod("createOrUpdate", 
AtlasEntitiesWithExtInfo.class, boolean.class, 
AtlasMetricsUtil.NotificationStat.class, PreprocessorContext.class);
+        Object entityProcessor = getEntityProcessor(hookConsumer);
+        Method createOrUpdateMethod = 
SerialEntityProcessor.class.getDeclaredMethod("createOrUpdate", 
AtlasEntitiesWithExtInfo.class, boolean.class, 
AtlasMetricsUtil.NotificationStat.class, PreprocessorContext.class);
         createOrUpdateMethod.setAccessible(true);
 
         // Create entities with more than batch size
@@ -796,7 +806,7 @@ public class NotificationHookConsumerTest {
         
when(mockResponse.getDeletedEntities()).thenReturn(Collections.emptyList());
         when(atlasEntityStore.createOrUpdate(any(AtlasEntityStream.class), 
eq(false))).thenReturn(mockResponse);
 
-        createOrUpdateMethod.invoke(hookConsumer, entitiesWithExtInfo, false, 
stats, context);
+        createOrUpdateMethod.invoke(entityProcessor, entitiesWithExtInfo, 
false, stats, context);
 
         verify(atlasEntityStore, 
times(3)).createOrUpdate(any(AtlasEntityStream.class), eq(false));
     }
@@ -807,7 +817,8 @@ public class NotificationHookConsumerTest {
         NotificationConsumer<HookNotification> notificationConsumer = 
mock(NotificationConsumer.class);
         Object hookConsumer = createHookConsumer(consumer, 
notificationConsumer);
 
-        Method createOrUpdateMethod = 
hookConsumer.getClass().getDeclaredMethod("createOrUpdate", 
AtlasEntitiesWithExtInfo.class, boolean.class, 
AtlasMetricsUtil.NotificationStat.class, PreprocessorContext.class);
+        Object entityProcessor = getEntityProcessor(hookConsumer);
+        Method createOrUpdateMethod = 
SerialEntityProcessor.class.getDeclaredMethod("createOrUpdate", 
AtlasEntitiesWithExtInfo.class, boolean.class, 
AtlasMetricsUtil.NotificationStat.class, PreprocessorContext.class);
         createOrUpdateMethod.setAccessible(true);
 
         AtlasEntity entity = new AtlasEntity("TestType");
@@ -828,7 +839,7 @@ public class NotificationHookConsumerTest {
         
when(mockResponse.getDeletedEntities()).thenReturn(Collections.emptyList());
         when(atlasEntityStore.createOrUpdate(any(AtlasEntityStream.class), 
anyBoolean())).thenReturn(mockResponse);
 
-        createOrUpdateMethod.invoke(hookConsumer, entitiesWithExtInfo, false, 
stats, context);
+        createOrUpdateMethod.invoke(entityProcessor, entitiesWithExtInfo, 
false, stats, context);
 
         verify(atlasEntityStore, 
times(2)).createOrUpdate(any(AtlasEntityStream.class), anyBoolean());
         verify(context).prepareForPostUpdate();
@@ -836,59 +847,25 @@ public class NotificationHookConsumerTest {
 
     @Test
     public void testAdaptiveWaiterWithDifferentExceptions() throws Exception {
-        NotificationHookConsumer consumer = createTestConsumer();
-
-        Class<?> adaptiveWaiterClass = 
getInnerClass(NotificationHookConsumer.class, "AdaptiveWaiter");
-        Object adaptiveWaiter = 
adaptiveWaiterClass.getDeclaredConstructor(long.class, long.class, long.class)
-                .newInstance(100L, 5000L, 100L);
-
-        Method pauseMethod = adaptiveWaiterClass.getDeclaredMethod("pause", 
Throwable.class);
-        pauseMethod.setAccessible(true);
+        AdaptiveWaiter adaptiveWaiter = new AdaptiveWaiter(100L, 5000L, 100L);
 
-        // Test with different exception types
-        pauseMethod.invoke(adaptiveWaiter, new RuntimeException("Test runtime 
exception"));
-        pauseMethod.invoke(adaptiveWaiter, new IllegalStateException("Test 
illegal state"));
-        pauseMethod.invoke(adaptiveWaiter, new AtlasBaseException("Test atlas 
exception"));
+        adaptiveWaiter.pause(new RuntimeException("Test runtime exception"));
+        adaptiveWaiter.pause(new IllegalStateException("Test illegal state"));
+        adaptiveWaiter.pause(new AtlasBaseException("Test atlas exception"));
 
-        Field waitDurationField = 
adaptiveWaiterClass.getDeclaredField("waitDuration");
-        waitDurationField.setAccessible(true);
-        long waitDuration = (Long) waitDurationField.get(adaptiveWaiter);
-
-        // Should have increased wait duration after multiple pauses
-        assertTrue(waitDuration > 100L);
+        assertTrue(adaptiveWaiter.waitDuration > 100L);
     }
 
     @Test
     public void testAdaptiveWaiterResetAfterLongInterval() throws Exception {
-        NotificationHookConsumer consumer = createTestConsumer();
+        AdaptiveWaiter adaptiveWaiter = new AdaptiveWaiter(100L, 1000L, 100L);
 
-        Class<?> adaptiveWaiterClass = 
getInnerClass(NotificationHookConsumer.class, "AdaptiveWaiter");
-        Object adaptiveWaiter = 
adaptiveWaiterClass.getDeclaredConstructor(long.class, long.class, long.class)
-                .newInstance(100L, 1000L, 100L);
+        adaptiveWaiter.pause(new RuntimeException("Test"));
+        Thread.sleep(2500); // resetInterval = maxDuration * 2
 
-        Method pauseMethod = adaptiveWaiterClass.getDeclaredMethod("pause", 
Throwable.class);
-        pauseMethod.setAccessible(true);
+        adaptiveWaiter.pause(new RuntimeException("Test again"));
 
-        Method setWaitDurationsMethod = 
adaptiveWaiterClass.getDeclaredMethod("setWaitDurations");
-        setWaitDurationsMethod.setAccessible(true);
-
-        Field lastWaitAtField = 
adaptiveWaiterClass.getDeclaredField("lastWaitAt");
-        lastWaitAtField.setAccessible(true);
-
-        // Simulate wait
-        pauseMethod.invoke(adaptiveWaiter, new RuntimeException("Test"));
-
-        // Set lastWaitAt to simulate long interval
-        lastWaitAtField.set(adaptiveWaiter, System.currentTimeMillis() - 
10000);
-
-        // Should reset wait duration due to long interval
-        setWaitDurationsMethod.invoke(adaptiveWaiter);
-
-        Field waitDurationField = 
adaptiveWaiterClass.getDeclaredField("waitDuration");
-        waitDurationField.setAccessible(true);
-        long waitDuration = (Long) waitDurationField.get(adaptiveWaiter);
-
-        assertEquals(100L, waitDuration); // Should be reset to minimum
+        assertEquals(100L, adaptiveWaiter.waitDuration);
     }
 
     @Test
@@ -1090,7 +1067,7 @@ public class NotificationHookConsumerTest {
 
     @Test
     public void testComplexPreprocessingScenarios() throws Exception {
-        NotificationHookConsumer consumer = 
createTestConsumerWithPreprocessing();
+        Object entityProcessor = createEntityProcessorWithPreprocessing();
 
         // Test complex entity with multiple relationships and attributes
         AtlasEntity complexEntity = new AtlasEntity("hive_table");
@@ -1110,10 +1087,10 @@ public class NotificationHookConsumerTest {
         EntityCreateRequestV2 createRequest = new 
EntityCreateRequestV2("testUser", entities);
         AtlasKafkaMessage<HookNotification> kafkaMsg = new 
AtlasKafkaMessage<>(createRequest, 1L, "test-topic", 0);
 
-        Method preProcessMethod = 
NotificationHookConsumer.class.getDeclaredMethod("preProcessNotificationMessage",
 AtlasKafkaMessage.class);
+        Method preProcessMethod = 
SerialEntityProcessor.class.getDeclaredMethod("preProcessNotificationMessage", 
AtlasKafkaMessage.class);
         preProcessMethod.setAccessible(true);
 
-        PreprocessorContext result = (PreprocessorContext) 
preProcessMethod.invoke(consumer, kafkaMsg);
+        PreprocessorContext result = (PreprocessorContext) 
preProcessMethod.invoke(entityProcessor, kafkaMsg);
 
         assertNotNull(result);
         verify(atlasEntityStore, never()).createOrUpdate(any(), anyBoolean()); 
// Just preprocessing
@@ -1143,9 +1120,10 @@ public class NotificationHookConsumerTest {
 
     @Test
     public void testHookConsumerMaxRetriesWithFailedMessageRecording() throws 
Exception {
-        NotificationHookConsumer consumer = 
createTestConsumerWithFailedMsgCache(2); // small cache
+        Configuration cacheConfig = buildFailedMsgCacheConfig(2);
+        NotificationHookConsumer consumer = createTestConsumer();
         NotificationConsumer<HookNotification> notificationConsumer = 
mock(NotificationConsumer.class);
-        Object hookConsumer = createHookConsumer(consumer, 
notificationConsumer);
+        Object hookConsumer = createHookConsumerWithEntityProcessor(consumer, 
notificationConsumer, createEntityProcessor(cacheConfig));
 
         Method handleMessageMethod = 
hookConsumer.getClass().getDeclaredMethod("handleMessage", 
AtlasKafkaMessage.class);
         handleMessageMethod.setAccessible(true);
@@ -1276,7 +1254,9 @@ public class NotificationHookConsumerTest {
         handleMessageMethod.invoke(hookConsumer, kafkaMsg);
         handleMessageMethod.invoke(hookConsumer, kafkaMsg);
 
-        verify(notificationConsumer, 
times(2)).commit(any(TopicPartition.class), anyLong());
+        // First message commits; second reuses the same offset and polls 
instead of committing again
+        verify(notificationConsumer, 
times(1)).commit(any(TopicPartition.class), anyLong());
+        verify(notificationConsumer, times(1)).poll();
     }
 
     @Test
@@ -1309,9 +1289,9 @@ public class NotificationHookConsumerTest {
 
     @Test
     public void testSkipHiveColumnLineageWithDuplicates() throws Exception {
-        NotificationHookConsumer consumer = 
createTestConsumerWithHiveLineageSkip();
+        Object entityProcessor = createEntityProcessorWithHiveLineageSkip();
 
-        Method skipHiveLineageMethod = 
NotificationHookConsumer.class.getDeclaredMethod("skipHiveColumnLineage", 
PreprocessorContext.class);
+        Method skipHiveLineageMethod = 
SerialEntityProcessor.class.getDeclaredMethod("skipHiveColumnLineage", 
PreprocessorContext.class);
         skipHiveLineageMethod.setAccessible(true);
 
         PreprocessorContext context = mock(PreprocessorContext.class);
@@ -1332,7 +1312,7 @@ public class NotificationHookConsumerTest {
         when(context.getKafkaMessageOffset()).thenReturn(100L);
         when(context.getKafkaPartition()).thenReturn(1);
 
-        skipHiveLineageMethod.invoke(consumer, context);
+        skipHiveLineageMethod.invoke(entityProcessor, context);
 
         verify(context, atLeast(1)).getEntities();
     }
@@ -1411,7 +1391,7 @@ public class NotificationHookConsumerTest {
     public void testEntityUpdateWithComplexRelationships() throws Exception {
         NotificationHookConsumer consumer = createTestConsumer();
 
-        Method updateReferencesMethod = 
NotificationHookConsumer.class.getDeclaredMethod("updateProcessedEntityReferences",
 List.class, Map.class);
+        Method updateReferencesMethod = 
SerialEntityProcessor.class.getDeclaredMethod("updateProcessedEntityReferences",
 List.class, Map.class);
         updateReferencesMethod.setAccessible(true);
 
         // Create entities with complex relationships
@@ -1448,7 +1428,7 @@ public class NotificationHookConsumerTest {
         guidAssignments.put("old-col1-guid", "new-col1-guid");
         guidAssignments.put("old-schema-guid", "new-schema-guid");
 
-        updateReferencesMethod.invoke(consumer, entities, guidAssignments);
+        updateReferencesMethod.invoke(getEntityProcessor(consumer), entities, 
guidAssignments);
 
         // Verify references were updated
         assertEquals("new-db-guid", ((AtlasObjectId) 
entity1.getAttribute("database")).getGuid());
@@ -1545,7 +1525,7 @@ public class NotificationHookConsumerTest {
 
     @Test
     public void testPreProcessNotificationMessage() throws Exception {
-        NotificationHookConsumer consumer = 
createTestConsumerWithPreprocessing();
+        Object entityProcessor = createEntityProcessorWithPreprocessing();
 
         // Create test message
         AtlasEntity entity = new AtlasEntity("hive_table");
@@ -1559,10 +1539,10 @@ public class NotificationHookConsumerTest {
                 new AtlasKafkaMessage<>(createRequest, 1L, "test-topic", 0);
 
         Method preProcessMethod =
-                
NotificationHookConsumer.class.getDeclaredMethod("preProcessNotificationMessage",
 AtlasKafkaMessage.class);
+                
SerialEntityProcessor.class.getDeclaredMethod("preProcessNotificationMessage", 
AtlasKafkaMessage.class);
         preProcessMethod.setAccessible(true);
 
-        PreprocessorContext result = (PreprocessorContext) 
preProcessMethod.invoke(consumer, kafkaMsg);
+        PreprocessorContext result = (PreprocessorContext) 
preProcessMethod.invoke(entityProcessor, kafkaMsg);
 
         assertNotNull(result, "Preprocessing should return a valid 
PreprocessorContext");
     }
@@ -1571,9 +1551,9 @@ public class NotificationHookConsumerTest {
 
     @Test
     public void testPreprocessEntities() throws Exception {
-        NotificationHookConsumer consumer = 
createTestConsumerWithPreprocessing();
+        Object entityProcessor = createEntityProcessorWithPreprocessing();
 
-        Method preprocessEntitiesMethod = 
NotificationHookConsumer.class.getDeclaredMethod("preprocessEntities", 
PreprocessorContext.class);
+        Method preprocessEntitiesMethod = 
SerialEntityProcessor.class.getDeclaredMethod("preprocessEntities", 
PreprocessorContext.class);
         preprocessEntitiesMethod.setAccessible(true);
 
         // Create mock context
@@ -1587,7 +1567,7 @@ public class NotificationHookConsumerTest {
         when(context.getReferredEntities()).thenReturn(new HashMap<>());
         when(context.isIgnoredEntity("test-guid")).thenReturn(false);
 
-        preprocessEntitiesMethod.invoke(consumer, context);
+        preprocessEntitiesMethod.invoke(entityProcessor, context);
 
         verify(context).getEntities();
     }
@@ -1596,13 +1576,13 @@ public class NotificationHookConsumerTest {
     public void testTrimAndPurgeMethod() throws Exception {
         NotificationHookConsumer consumer = createTestConsumer();
 
-        Method trimAndPurgeMethod = 
NotificationHookConsumer.class.getDeclaredMethod("trimAndPurge", 
String[].class, String.class);
+        Method trimAndPurgeMethod = 
SerialEntityProcessor.class.getDeclaredMethod("trimAndPurge", String[].class, 
String.class);
         trimAndPurgeMethod.setAccessible(true);
 
         // Test with valid values
         String[] input = {" value1 ", "", " value2", null, "value3 "};
         @SuppressWarnings("unchecked")
-        List<String> result = (List<String>) 
trimAndPurgeMethod.invoke(consumer, input, "default");
+        List<String> result = (List<String>) 
trimAndPurgeMethod.invoke(getEntityProcessor(consumer), input, "default");
 
         assertEquals(3, result.size());
         assertTrue(result.contains("value1"));
@@ -1611,13 +1591,13 @@ public class NotificationHookConsumerTest {
 
         // Test with null input
         @SuppressWarnings("unchecked")
-        List<String> defaultResult = (List<String>) 
trimAndPurgeMethod.invoke(consumer, null, "default");
+        List<String> defaultResult = (List<String>) 
trimAndPurgeMethod.invoke(getEntityProcessor(consumer), null, "default");
         assertEquals(1, defaultResult.size());
         assertEquals("default", defaultResult.get(0));
 
         // Test with empty default
         @SuppressWarnings("unchecked")
-        List<String> emptyResult = (List<String>) 
trimAndPurgeMethod.invoke(consumer, null, null);
+        List<String> emptyResult = (List<String>) 
trimAndPurgeMethod.invoke(getEntityProcessor(consumer), null, null);
         assertTrue(emptyResult.isEmpty());
     }
 
@@ -1625,7 +1605,7 @@ public class NotificationHookConsumerTest {
     public void testGetAuthenticationForUser() throws Exception {
         NotificationHookConsumer consumer = createTestConsumer();
 
-        Method getAuthMethod = 
NotificationHookConsumer.class.getDeclaredMethod("getAuthenticationForUser", 
String.class);
+        Method getAuthMethod = 
SerialEntityProcessor.class.getDeclaredMethod("getAuthenticationForUser", 
String.class);
         getAuthMethod.setAccessible(true);
 
         try 
(MockedStatic<org.apache.atlas.web.security.AtlasAbstractAuthenticationProvider>
 authProvider =
@@ -1633,14 +1613,14 @@ public class NotificationHookConsumerTest {
             authProvider.when(() -> 
org.apache.atlas.web.security.AtlasAbstractAuthenticationProvider.getAuthoritiesFromUGI("testUser"))
                     .thenReturn(new ArrayList<>());
 
-            Object auth = getAuthMethod.invoke(consumer, "testUser");
+            Object auth = getAuthMethod.invoke(getEntityProcessor(consumer), 
"testUser");
             assertNotNull(auth);
 
             // Test with null/empty username
-            Object nullAuth = getAuthMethod.invoke(consumer, (String) null);
+            Object nullAuth = 
getAuthMethod.invoke(getEntityProcessor(consumer), (String) null);
             assertNull(nullAuth);
 
-            Object emptyAuth = getAuthMethod.invoke(consumer, "");
+            Object emptyAuth = 
getAuthMethod.invoke(getEntityProcessor(consumer), "");
             assertNull(emptyAuth);
         }
     }
@@ -1649,7 +1629,7 @@ public class NotificationHookConsumerTest {
     public void testSetCurrentUser() throws Exception {
         NotificationHookConsumer consumer = createTestConsumer();
 
-        Method setCurrentUserMethod = 
NotificationHookConsumer.class.getDeclaredMethod("setCurrentUser", 
String.class);
+        Method setCurrentUserMethod = 
SerialEntityProcessor.class.getDeclaredMethod("setCurrentUser", String.class);
         setCurrentUserMethod.setAccessible(true);
 
         try 
(MockedStatic<org.apache.atlas.web.security.AtlasAbstractAuthenticationProvider>
 authProvider =
@@ -1664,7 +1644,7 @@ public class NotificationHookConsumerTest {
             
securityContext.when(org.springframework.security.core.context.SecurityContextHolder::getContext)
                     .thenReturn(mockContext);
 
-            setCurrentUserMethod.invoke(consumer, "testUser");
+            setCurrentUserMethod.invoke(getEntityProcessor(consumer), 
"testUser");
 
             verify(mockContext).setAuthentication(any());
         }
@@ -1674,7 +1654,7 @@ public class NotificationHookConsumerTest {
     public void testUpdateProcessedEntityReferencesAtlasObjectId() throws 
Exception {
         NotificationHookConsumer consumer = createTestConsumer();
 
-        Method updateMethod = 
NotificationHookConsumer.class.getDeclaredMethod("updateProcessedEntityReferences",
 AtlasObjectId.class, Map.class);
+        Method updateMethod = 
SerialEntityProcessor.class.getDeclaredMethod("updateProcessedEntityReferences",
 AtlasObjectId.class, Map.class);
         updateMethod.setAccessible(true);
 
         AtlasObjectId objectId = new AtlasObjectId("original-guid", 
"TestType");
@@ -1691,7 +1671,7 @@ public class NotificationHookConsumerTest {
     public void testUpdateProcessedEntityReferencesMap() throws Exception {
         NotificationHookConsumer consumer = createTestConsumer();
 
-        Method updateMethod = 
NotificationHookConsumer.class.getDeclaredMethod("updateProcessedEntityReferences",
 Map.class, Map.class);
+        Method updateMethod = 
SerialEntityProcessor.class.getDeclaredMethod("updateProcessedEntityReferences",
 Map.class, Map.class);
         updateMethod.setAccessible(true);
 
         Map<String, Object> objIdMap = new HashMap<>();
@@ -1702,7 +1682,7 @@ public class NotificationHookConsumerTest {
         Map<String, String> guidAssignments = new HashMap<>();
         guidAssignments.put("original-guid", "new-guid");
 
-        updateMethod.invoke(consumer, objIdMap, guidAssignments);
+        updateMethod.invoke(getEntityProcessor(consumer), objIdMap, 
guidAssignments);
 
         assertEquals("new-guid", objIdMap.get("guid"));
         assertFalse(objIdMap.containsKey("typeName"));
@@ -1713,7 +1693,7 @@ public class NotificationHookConsumerTest {
     public void testUpdateProcessedEntityReferencesCollection() throws 
Exception {
         NotificationHookConsumer consumer = createTestConsumer();
 
-        Method updateMethod = 
NotificationHookConsumer.class.getDeclaredMethod("updateProcessedEntityReferences",
 Collection.class, Map.class);
+        Method updateMethod = 
SerialEntityProcessor.class.getDeclaredMethod("updateProcessedEntityReferences",
 Collection.class, Map.class);
         updateMethod.setAccessible(true);
 
         AtlasObjectId objectId1 = new AtlasObjectId("guid1", "TestType1");
@@ -1729,7 +1709,7 @@ public class NotificationHookConsumerTest {
         assertEquals("guid2", objectId2.getGuid());
         assertEquals("TestType2", objectId2.getTypeName());
 
-        updateMethod.invoke(consumer, collection, guidAssignments);
+        updateMethod.invoke(getEntityProcessor(consumer), collection, 
guidAssignments);
 
         // objectId1 should be updated, objectId2 should remain unchanged
         assertEquals("new-guid1", objectId1.getGuid());
@@ -1742,7 +1722,7 @@ public class NotificationHookConsumerTest {
     public void testRecordProcessedEntities() throws Exception {
         NotificationHookConsumer consumer = createTestConsumer();
 
-        Method recordMethod = 
NotificationHookConsumer.class.getDeclaredMethod("recordProcessedEntities", 
EntityMutationResponse.class, AtlasMetricsUtil.NotificationStat.class, 
PreprocessorContext.class);
+        Method recordMethod = 
SerialEntityProcessor.class.getDeclaredMethod("recordProcessedEntities", 
EntityMutationResponse.class, AtlasMetricsUtil.NotificationStat.class, 
PreprocessorContext.class);
         recordMethod.setAccessible(true);
 
         EntityMutationResponse mutationResponse = 
mock(EntityMutationResponse.class);
@@ -1756,7 +1736,7 @@ public class NotificationHookConsumerTest {
         when(context.getCreatedEntities()).thenReturn(Collections.emptySet());
         when(context.getDeletedEntities()).thenReturn(Collections.emptySet());
 
-        recordMethod.invoke(consumer, mutationResponse, stats, context);
+        recordMethod.invoke(getEntityProcessor(consumer), mutationResponse, 
stats, context);
 
         verify(stats).updateStats(mutationResponse);
         verify(context).getGuidAssignments();
@@ -1766,28 +1746,28 @@ public class NotificationHookConsumerTest {
     public void testIsEmptyMessageForDifferentTypes() throws Exception {
         NotificationHookConsumer consumer = createTestConsumer();
 
-        Method isEmptyMethod = 
NotificationHookConsumer.class.getDeclaredMethod("isEmptyMessage", 
AtlasKafkaMessage.class);
+        Method isEmptyMethod = 
SerialEntityProcessor.class.getDeclaredMethod("isEmptyMessage", 
AtlasKafkaMessage.class);
         isEmptyMethod.setAccessible(true);
 
         // Test CREATE_V2 with empty entities
         EntityCreateRequestV2 emptyCreate = new EntityCreateRequestV2("user", 
new AtlasEntitiesWithExtInfo());
         AtlasKafkaMessage<HookNotification> emptyCreateMsg = new 
AtlasKafkaMessage<>(emptyCreate, 1L, "topic", 0);
-        assertTrue((Boolean) isEmptyMethod.invoke(consumer, emptyCreateMsg));
+        assertTrue((Boolean) 
isEmptyMethod.invoke(getEntityProcessor(consumer), emptyCreateMsg));
 
         // Test CREATE_V2 with null entities
         EntityCreateRequestV2 nullCreate = new EntityCreateRequestV2("user", 
null);
         AtlasKafkaMessage<HookNotification> nullCreateMsg = new 
AtlasKafkaMessage<>(nullCreate, 1L, "topic", 0);
-        assertTrue((Boolean) isEmptyMethod.invoke(consumer, nullCreateMsg));
+        assertTrue((Boolean) 
isEmptyMethod.invoke(getEntityProcessor(consumer), nullCreateMsg));
 
         // Test UPDATE_V2 with empty entities
         EntityUpdateRequestV2 emptyUpdate = new EntityUpdateRequestV2("user", 
new AtlasEntitiesWithExtInfo());
         AtlasKafkaMessage<HookNotification> emptyUpdateMsg = new 
AtlasKafkaMessage<>(emptyUpdate, 1L, "topic", 0);
-        assertTrue((Boolean) isEmptyMethod.invoke(consumer, emptyUpdateMsg));
+        assertTrue((Boolean) 
isEmptyMethod.invoke(getEntityProcessor(consumer), emptyUpdateMsg));
 
         // Test other message types (should return false)
         EntityDeleteRequestV2 deleteRequest = new 
EntityDeleteRequestV2("user", Collections.emptyList());
         AtlasKafkaMessage<HookNotification> deleteMsg = new 
AtlasKafkaMessage<>(deleteRequest, 1L, "topic", 0);
-        assertFalse((Boolean) isEmptyMethod.invoke(consumer, deleteMsg));
+        assertFalse((Boolean) 
isEmptyMethod.invoke(getEntityProcessor(consumer), deleteMsg));
     }
 
     @Test
@@ -1863,18 +1843,19 @@ public class NotificationHookConsumerTest {
         NotificationConsumer<HookNotification> notificationConsumer = 
mock(NotificationConsumer.class);
         Object hookConsumer = createHookConsumer(consumer, 
notificationConsumer);
 
-        Method recordFailedMethod = 
hookConsumer.getClass().getDeclaredMethod("recordFailedMessages");
+        Object entityProcessor = getEntityProcessor(hookConsumer);
+        Method recordFailedMethod = 
SerialEntityProcessor.class.getDeclaredMethod("recordFailedMessages", 
List.class);
         recordFailedMethod.setAccessible(true);
 
         // Add some failed messages
-        Field failedMessagesField = 
hookConsumer.getClass().getDeclaredField("failedMessages");
+        Field failedMessagesField = 
SerialEntityProcessor.class.getDeclaredField("failedMessages");
         failedMessagesField.setAccessible(true);
         @SuppressWarnings("unchecked")
-        List<String> failedMessages = (List<String>) 
failedMessagesField.get(hookConsumer);
+        List<String> failedMessages = (List<String>) 
failedMessagesField.get(entityProcessor);
         failedMessages.add("failed message 1");
         failedMessages.add("failed message 2");
 
-        recordFailedMethod.invoke(hookConsumer);
+        recordFailedMethod.invoke(entityProcessor, failedMessages);
 
         assertTrue(failedMessages.isEmpty()); // Should be cleared after 
recording
     }
@@ -2021,27 +2002,15 @@ public class NotificationHookConsumerTest {
     public void testConstructorWithExceptionInConfigurationAccess() throws 
Exception {
         Configuration faultyConfig = mock(Configuration.class);
 
-        // Make config throw error on access
+        
when(faultyConfig.getInt(NotificationHookConsumer.CONSUMER_FAILEDCACHESIZE_PROPERTY,
 1)).thenReturn(1);
         
when(faultyConfig.getInt(NotificationHookConsumer.CONSUMER_RETRIES_PROPERTY, 3))
                 .thenThrow(new RuntimeException("Config access error"));
-        // Add other config properties to prevent NPE
-        
when(faultyConfig.getBoolean("atlas.notification.create.shell.entity.for.non.existing.ref",
 false))
-                .thenReturn(false);
-        
when(faultyConfig.getInt("atlas.notification.hook.consumer.buffering.interval", 
10))
-                .thenReturn(10);
-        
when(faultyConfig.getInt("atlas.notification.hook.consumer.buffering.batch.size",
 25))
-                .thenReturn(25);
-
-        try (MockedStatic<ApplicationProperties> appProps = 
mockStatic(ApplicationProperties.class)) {
-            appProps.when(ApplicationProperties::get).thenReturn(faultyConfig);
 
-            try {
-                new NotificationHookConsumer(notificationInterface, 
atlasEntityStore, serviceState,
-                        instanceConverter, typeRegistry, metricsUtil, 
entityCorrelationStore, asyncImporter);
-                fail("Expected exception due to config access error");
-            } catch (Exception e) {
-                assertTrue(e.getMessage().contains("Config access error") || 
e.getCause().getMessage().contains("Config access error"));
-            }
+        try {
+            createEntityProcessor(faultyConfig);
+            fail("Expected exception due to config access error");
+        } catch (RuntimeException e) {
+            assertTrue(e.getMessage().contains("Config access error"));
         }
     }
 
@@ -2127,9 +2096,9 @@ public class NotificationHookConsumerTest {
 
     @Test
     public void testPreprocessHiveTypes() throws Exception {
-        NotificationHookConsumer consumer = 
createTestConsumerWithPreprocessing();
+        Object entityProcessor = createEntityProcessorWithPreprocessing();
 
-        Method preprocessHiveTypesMethod = 
NotificationHookConsumer.class.getDeclaredMethod("preprocessHiveTypes", 
PreprocessorContext.class);
+        Method preprocessHiveTypesMethod = 
SerialEntityProcessor.class.getDeclaredMethod("preprocessHiveTypes", 
PreprocessorContext.class);
         preprocessHiveTypesMethod.setAccessible(true);
 
         PreprocessorContext context = mock(PreprocessorContext.class);
@@ -2140,7 +2109,7 @@ public class NotificationHookConsumerTest {
         List<AtlasEntity> entities = Collections.singletonList(hiveTable);
         when(context.getEntities()).thenReturn(entities);
 
-        preprocessHiveTypesMethod.invoke(consumer, context);
+        preprocessHiveTypesMethod.invoke(entityProcessor, context);
 
         verify(context).getEntities();
     }
@@ -2149,9 +2118,9 @@ public class NotificationHookConsumerTest {
 
     @Test
     public void testSkipHiveColumnLineage() throws Exception {
-        NotificationHookConsumer consumer = 
createTestConsumerWithPreprocessing();
+        Object entityProcessor = createEntityProcessorWithPreprocessing();
 
-        Method skipHiveLineageMethod = 
NotificationHookConsumer.class.getDeclaredMethod("skipHiveColumnLineage", 
PreprocessorContext.class);
+        Method skipHiveLineageMethod = 
SerialEntityProcessor.class.getDeclaredMethod("skipHiveColumnLineage", 
PreprocessorContext.class);
         skipHiveLineageMethod.setAccessible(true);
 
         PreprocessorContext context = mock(PreprocessorContext.class);
@@ -2169,16 +2138,16 @@ public class NotificationHookConsumerTest {
         when(context.getReferredEntities()).thenReturn(new HashMap<>());
 
         // This is a void method, so just verify it executes without exception
-        skipHiveLineageMethod.invoke(consumer, context);
+        skipHiveLineageMethod.invoke(entityProcessor, context);
 
         verify(context, atLeast(1)).getEntities();
     }
 
     @Test
     public void testRdbmsTypeRemoveOwnedRefAttrs() throws Exception {
-        NotificationHookConsumer consumer = 
createTestConsumerWithPreprocessing();
+        Object entityProcessor = createEntityProcessorWithPreprocessing();
 
-        Method rdbmsRemoveMethod = 
NotificationHookConsumer.class.getDeclaredMethod("rdbmsTypeRemoveOwnedRefAttrs",
 PreprocessorContext.class);
+        Method rdbmsRemoveMethod = 
SerialEntityProcessor.class.getDeclaredMethod("rdbmsTypeRemoveOwnedRefAttrs", 
PreprocessorContext.class);
         rdbmsRemoveMethod.setAccessible(true);
 
         PreprocessorContext context = mock(PreprocessorContext.class);
@@ -2189,16 +2158,16 @@ public class NotificationHookConsumerTest {
         List<AtlasEntity> entities = Collections.singletonList(rdbmsTable);
         when(context.getEntities()).thenReturn(entities);
 
-        rdbmsRemoveMethod.invoke(consumer, context);
+        rdbmsRemoveMethod.invoke(entityProcessor, context);
 
         verify(context).getEntities();
     }
 
     @Test
     public void testPruneObjectPrefixForS3V2Directory() throws Exception {
-        NotificationHookConsumer consumer = 
createTestConsumerWithPreprocessing();
+        Object entityProcessor = createEntityProcessorWithPreprocessing();
 
-        Method pruneMethod = 
NotificationHookConsumer.class.getDeclaredMethod("pruneObjectPrefixForS3V2Directory",
 PreprocessorContext.class);
+        Method pruneMethod = 
SerialEntityProcessor.class.getDeclaredMethod("pruneObjectPrefixForS3V2Directory",
 PreprocessorContext.class);
         pruneMethod.setAccessible(true);
 
         PreprocessorContext context = mock(PreprocessorContext.class);
@@ -2208,16 +2177,16 @@ public class NotificationHookConsumerTest {
         List<AtlasEntity> entities = Collections.singletonList(s3Object);
         when(context.getEntities()).thenReturn(entities);
 
-        pruneMethod.invoke(consumer, context);
+        pruneMethod.invoke(entityProcessor, context);
 
         verify(context, atLeast(1)).getEntities();
     }
 
     @Test
     public void testPreprocessSparkProcessAttributes() throws Exception {
-        NotificationHookConsumer consumer = 
createTestConsumerWithPreprocessing();
+        Object entityProcessor = createEntityProcessorWithPreprocessing();
 
-        Method sparkPreprocessMethod = 
NotificationHookConsumer.class.getDeclaredMethod("preprocessSparkProcessAttributes",
 PreprocessorContext.class);
+        Method sparkPreprocessMethod = 
SerialEntityProcessor.class.getDeclaredMethod("preprocessSparkProcessAttributes",
 PreprocessorContext.class);
         sparkPreprocessMethod.setAccessible(true);
 
         PreprocessorContext context = mock(PreprocessorContext.class);
@@ -2227,7 +2196,7 @@ public class NotificationHookConsumerTest {
         List<AtlasEntity> entities = Collections.singletonList(sparkProcess);
         when(context.getEntities()).thenReturn(entities);
 
-        sparkPreprocessMethod.invoke(consumer, context);
+        sparkPreprocessMethod.invoke(entityProcessor, context);
 
         verify(context).getEntities();
     }
@@ -2236,7 +2205,7 @@ public class NotificationHookConsumerTest {
     public void testUpdateProcessedEntityReferencesObject() throws Exception {
         NotificationHookConsumer consumer = createTestConsumer();
 
-        Method updateMethod = 
NotificationHookConsumer.class.getDeclaredMethod("updateProcessedEntityReferences",
 Object.class, Map.class);
+        Method updateMethod = 
SerialEntityProcessor.class.getDeclaredMethod("updateProcessedEntityReferences",
 Object.class, Map.class);
         updateMethod.setAccessible(true);
 
         // Test with AtlasObjectId
@@ -2248,7 +2217,7 @@ public class NotificationHookConsumerTest {
         assertEquals("original-guid", objectId.getGuid());
         assertEquals("TestType", objectId.getTypeName());
 
-        updateMethod.invoke(consumer, objectId, guidAssignments);
+        updateMethod.invoke(getEntityProcessor(consumer), objectId, 
guidAssignments);
         assertEquals("new-guid", objectId.getGuid());
         assertNull(objectId.getTypeName()); // cleared after GUID assignment
 
@@ -2258,14 +2227,14 @@ public class NotificationHookConsumerTest {
         objIdMap.put("typeName", "MapType");
         guidAssignments.put("map-guid", "new-map-guid");
 
-        updateMethod.invoke(consumer, objIdMap, guidAssignments);
+        updateMethod.invoke(getEntityProcessor(consumer), objIdMap, 
guidAssignments);
         assertEquals("new-map-guid", objIdMap.get("guid"));
 
         // Test with Collection
         List<AtlasObjectId> collection = Collections.singletonList(new 
AtlasObjectId("Type1", "collection-guid"));
         guidAssignments.put("collection-guid", "new-collection-guid");
 
-        updateMethod.invoke(consumer, collection, guidAssignments);
+        updateMethod.invoke(getEntityProcessor(consumer), collection, 
guidAssignments);
     }
 
     @Test
@@ -2430,7 +2399,7 @@ public class NotificationHookConsumerTest {
     public void testSetCurrentUserWithAuthorizationEnabled() throws Exception {
         NotificationHookConsumer consumer = 
createTestConsumerWithAuthorization();
 
-        Method setCurrentUserMethod = 
NotificationHookConsumer.class.getDeclaredMethod("setCurrentUser", 
String.class);
+        Method setCurrentUserMethod = 
SerialEntityProcessor.class.getDeclaredMethod("setCurrentUser", String.class);
         setCurrentUserMethod.setAccessible(true);
 
         try 
(MockedStatic<org.apache.atlas.web.security.AtlasAbstractAuthenticationProvider>
 authProvider =
@@ -2445,7 +2414,7 @@ public class NotificationHookConsumerTest {
             
securityContext.when(org.springframework.security.core.context.SecurityContextHolder::getContext)
                     .thenReturn(mockContext);
 
-            setCurrentUserMethod.invoke(consumer, "testUser");
+            setCurrentUserMethod.invoke(getEntityProcessor(consumer), 
"testUser");
 
             verify(mockContext).setAuthentication(any());
         }
@@ -2457,7 +2426,7 @@ public class NotificationHookConsumerTest {
     public void testGetAuthenticationForUserWithCache() throws Exception {
         NotificationHookConsumer consumer = 
createTestConsumerWithAuthorization();
 
-        Method getAuthMethod = 
NotificationHookConsumer.class.getDeclaredMethod("getAuthenticationForUser", 
String.class);
+        Method getAuthMethod = 
SerialEntityProcessor.class.getDeclaredMethod("getAuthenticationForUser", 
String.class);
         getAuthMethod.setAccessible(true);
 
         try 
(MockedStatic<org.apache.atlas.web.security.AtlasAbstractAuthenticationProvider>
 authProvider =
@@ -2466,11 +2435,11 @@ public class NotificationHookConsumerTest {
                     .thenReturn(new ArrayList<>());
 
             // First call - should cache
-            Object auth1 = getAuthMethod.invoke(consumer, "cachedUser");
+            Object auth1 = getAuthMethod.invoke(getEntityProcessor(consumer), 
"cachedUser");
             assertNotNull(auth1);
 
             // Second call - should use cache
-            Object auth2 = getAuthMethod.invoke(consumer, "cachedUser");
+            Object auth2 = getAuthMethod.invoke(getEntityProcessor(consumer), 
"cachedUser");
             assertNotNull(auth2);
 
             // Should only call the static method once due to caching
@@ -2483,7 +2452,7 @@ public class NotificationHookConsumerTest {
     public void testIsEmptyMessageWithNullMessage() throws Exception {
         NotificationHookConsumer consumer = createTestConsumer();
 
-        Method isEmptyMethod = NotificationHookConsumer.class
+        Method isEmptyMethod = SerialEntityProcessor.class
                 .getDeclaredMethod("isEmptyMessage", AtlasKafkaMessage.class);
         isEmptyMethod.setAccessible(true);
 
@@ -2491,7 +2460,7 @@ public class NotificationHookConsumerTest {
                 new AtlasKafkaMessage<>(null, 1L, "topic", 0);
 
         try {
-            isEmptyMethod.invoke(consumer, nullMessage);
+            isEmptyMethod.invoke(getEntityProcessor(consumer), nullMessage);
             fail("Expected NullPointerException but none thrown");
         } catch (InvocationTargetException e) {
             assertTrue(e.getCause() instanceof NullPointerException,
@@ -2587,6 +2556,95 @@ public class NotificationHookConsumerTest {
         }
     }
 
+    private Configuration buildBatchingConfig(int batchSize) {
+        Configuration batchConfig = mock(Configuration.class);
+        
when(batchConfig.getInt(NotificationHookConsumer.CONSUMER_COMMIT_BATCH_SIZE, 
50)).thenReturn(batchSize);
+        
when(batchConfig.getInt(NotificationHookConsumer.CONSUMER_RETRIES_PROPERTY, 
3)).thenReturn(3);
+        
when(batchConfig.getBoolean("atlas.notification.create.shell.entity.for.non.existing.ref",
 false)).thenReturn(false);
+        
when(batchConfig.getInt("atlas.notification.hook.consumer.buffering.interval", 
10)).thenReturn(10);
+        
when(batchConfig.getInt("atlas.notification.hook.consumer.buffering.batch.size",
 25)).thenReturn(25);
+        
when(batchConfig.getBoolean("atlas.notification.consumer.create.shell.entity.for.non-existing.ref",
 true)).thenReturn(false);
+        
when(batchConfig.getInt("atlas.notification.consumer.message.buffering.interval.seconds",
 15)).thenReturn(10);
+        
when(batchConfig.getInt("atlas.notification.consumer.message.buffering.batch.size",
 100)).thenReturn(25);
+        return batchConfig;
+    }
+
+    private Configuration buildFailedMsgCacheConfig(int cacheSize) {
+        Configuration cacheConfig = mock(Configuration.class);
+        
when(cacheConfig.getInt(NotificationHookConsumer.CONSUMER_FAILEDCACHESIZE_PROPERTY,
 1)).thenReturn(cacheSize);
+        
when(cacheConfig.getInt(NotificationHookConsumer.CONSUMER_RETRIES_PROPERTY, 
3)).thenReturn(3);
+        
when(cacheConfig.getBoolean("atlas.notification.create.shell.entity.for.non.existing.ref",
 false)).thenReturn(false);
+        
when(cacheConfig.getInt("atlas.notification.hook.consumer.buffering.interval", 
10)).thenReturn(10);
+        
when(cacheConfig.getInt("atlas.notification.hook.consumer.buffering.batch.size",
 25)).thenReturn(25);
+        
when(cacheConfig.getBoolean("atlas.notification.consumer.create.shell.entity.for.non-existing.ref",
 true)).thenReturn(false);
+        
when(cacheConfig.getInt("atlas.notification.consumer.message.buffering.interval.seconds",
 15)).thenReturn(10);
+        
when(cacheConfig.getInt("atlas.notification.consumer.message.buffering.batch.size",
 100)).thenReturn(25);
+        return cacheConfig;
+    }
+
+    private Object createEntityProcessor(Configuration configuration) throws 
Exception {
+        return new SerialEntityProcessor(
+                configuration,
+                metricsUtil,
+                null,
+                atlasEntityStore,
+                instanceConverter,
+                new EntityCorrelationManager(entityCorrelationStore),
+                typeRegistry,
+                LoggerFactory.getLogger("FAILED"),
+                LoggerFactory.getLogger("LARGE_MESSAGES"),
+                asyncImporter);
+    }
+
+    private Object createEntityProcessorWithPreprocessing() throws Exception {
+        Configuration preprocessingConfig = mock(Configuration.class);
+        
when(preprocessingConfig.getBoolean(NotificationHookConsumer.CONSUMER_PREPROCESS_HIVE_TYPES_REMOVE_OWNEDREF_ATTRS,
 true)).thenReturn(true);
+        
when(preprocessingConfig.getStringArray(NotificationHookConsumer.CONSUMER_PREPROCESS_HIVE_TABLE_IGNORE_PATTERN)).thenReturn(new
 String[] {"temp_.*"});
+        
when(preprocessingConfig.getInt(NotificationHookConsumer.CONSUMER_RETRIES_PROPERTY,
 3)).thenReturn(3);
+        
when(preprocessingConfig.getBoolean("atlas.notification.create.shell.entity.for.non.existing.ref",
 false)).thenReturn(true);
+        
when(preprocessingConfig.getInt("atlas.notification.hook.consumer.buffering.interval",
 10)).thenReturn(10);
+        
when(preprocessingConfig.getInt("atlas.notification.hook.consumer.buffering.batch.size",
 25)).thenReturn(25);
+        
when(preprocessingConfig.getBoolean("atlas.notification.consumer.create.shell.entity.for.non-existing.ref",
 true)).thenReturn(false);
+        
when(preprocessingConfig.getInt("atlas.notification.consumer.message.buffering.interval.seconds",
 15)).thenReturn(10);
+        
when(preprocessingConfig.getInt("atlas.notification.consumer.message.buffering.batch.size",
 100)).thenReturn(25);
+        return createEntityProcessor(preprocessingConfig);
+    }
+
+    private Object createEntityProcessorWithHiveLineageSkip() throws Exception 
{
+        Configuration skipConfig = mock(Configuration.class);
+        
when(skipConfig.getBoolean(NotificationHookConsumer.CONSUMER_SKIP_HIVE_COLUMN_LINEAGE_HIVE_20633,
 false)).thenReturn(true);
+        
when(skipConfig.getInt(NotificationHookConsumer.CONSUMER_SKIP_HIVE_COLUMN_LINEAGE_HIVE_20633_INPUTS_THRESHOLD,
 15)).thenReturn(1);
+        
when(skipConfig.getInt(NotificationHookConsumer.CONSUMER_RETRIES_PROPERTY, 
3)).thenReturn(3);
+        
when(skipConfig.getBoolean("atlas.notification.create.shell.entity.for.non.existing.ref",
 false)).thenReturn(false);
+        
when(skipConfig.getInt("atlas.notification.hook.consumer.buffering.interval", 
10)).thenReturn(10);
+        
when(skipConfig.getInt("atlas.notification.hook.consumer.buffering.batch.size", 
25)).thenReturn(25);
+        
when(skipConfig.getBoolean("atlas.notification.consumer.create.shell.entity.for.non-existing.ref",
 true)).thenReturn(false);
+        
when(skipConfig.getInt("atlas.notification.consumer.message.buffering.interval.seconds",
 15)).thenReturn(10);
+        
when(skipConfig.getInt("atlas.notification.consumer.message.buffering.batch.size",
 100)).thenReturn(25);
+        return createEntityProcessor(skipConfig);
+    }
+
+    private Object getEntityProcessor(Object hookConsumer) throws Exception {
+        Field field = 
hookConsumer.getClass().getDeclaredField("entityProcessor");
+        field.setAccessible(true);
+        return field.get(hookConsumer);
+    }
+
+    private Object getEntityProcessor(NotificationHookConsumer consumer) 
throws Exception {
+        return getEntityProcessor(createHookConsumer(consumer, 
mock(NotificationConsumer.class)));
+    }
+
+    private Object createHookConsumerWithEntityProcessor(
+            NotificationHookConsumer notificationHookConsumer,
+            NotificationConsumer<HookNotification> notificationConsumer,
+            Object entityProcessor) throws Exception {
+        Object hookConsumer = createHookConsumer(notificationHookConsumer, 
notificationConsumer);
+        Field field = 
hookConsumer.getClass().getDeclaredField("entityProcessor");
+        field.setAccessible(true);
+        field.set(hookConsumer, entityProcessor);
+        return hookConsumer;
+    }
+
     private Object createHookConsumer(NotificationHookConsumer consumer, 
NotificationConsumer<HookNotification> notificationConsumer) throws Exception {
         Class<?> hookConsumerClass = 
getInnerClass(NotificationHookConsumer.class, "HookConsumer");
         return 
hookConsumerClass.getDeclaredConstructor(NotificationHookConsumer.class, 
NotificationConsumer.class)

Reply via email to