Alert Test Fix (#9640)

* Alert Test Fix

* Removed Db calls in case local publishers available

* Fix test

* Removed unrequired code

* Maintaing entityType to class map

* checkstyle
This commit is contained in:
Mohit Yadav 2023-01-10 12:56:10 +05:30 committed by GitHub
parent 8255e4685b
commit ea0e0e03e4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 81 additions and 57 deletions

View File

@ -163,7 +163,7 @@ public final class Entity {
DAO_MAP.put(entity, dao);
ENTITY_REPOSITORY_MAP.put(entity, entityRepository);
EntityInterface.CANONICAL_ENTITY_NAME_MAP.put(entity.toLowerCase(Locale.ROOT), entity);
EntityInterface.ENTITY_TYPE_TO_CLASS_MAP.put(entity.toLowerCase(Locale.ROOT), clazz);
ENTITY_LIST.add(entity);
Collections.sort(ENTITY_LIST);
@ -287,6 +287,10 @@ public final class Entity {
return EntityInterface.CANONICAL_ENTITY_NAME_MAP.get(object.getClass().getSimpleName().toLowerCase(Locale.ROOT));
}
public static Class<? extends EntityInterface> getEntityClassFromType(String entityType) {
return EntityInterface.ENTITY_TYPE_TO_CLASS_MAP.get(entityType);
}
/**
* Get list of all the entity field names from JsonPropertyOrder annotation from generated java class from entity.json
*/

View File

@ -1,11 +1,10 @@
package org.openmetadata.service.alerts;
import static org.openmetadata.schema.type.Relationship.CONTAINS;
import static org.openmetadata.service.Entity.ALERT;
import static org.openmetadata.service.Entity.ALERT_ACTION;
import com.lmax.disruptor.BatchEventProcessor;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -68,17 +67,6 @@ public class AlertsPublisherManager {
}
public void addAlertActionPublisher(Alert alert, AlertAction alertAction) {
if (Boolean.FALSE.equals(alertAction.getEnabled())) {
// Only add alert that is enabled for publishing events
AlertActionStatus status =
new AlertActionStatus()
.withStatus(AlertActionStatus.Status.DISABLED)
.withTimestamp(System.currentTimeMillis())
.withFailureDetails(null);
alertAction.setStatusDetails(status);
return;
}
// Activity Feed AlertAction Cannot be Created
if (alertAction.getAlertActionType() == AlertAction.AlertActionType.ACTIVITY_FEED) {
LOG.info("Activity Feed Alert Action cannot be created.");
@ -86,9 +74,19 @@ public class AlertsPublisherManager {
}
// Create AlertAction Publisher
AlertsActionPublisher publisher = AlertUtil.getAlertPublisher(alert, alertAction, daoCollection);
BatchEventProcessor<EventPubSub.ChangeEventHolder> processor = EventPubSub.addEventHandler(publisher);
publisher.setProcessor(processor);
LOG.info("Alert publisher started for {}", alert.getName());
if (Boolean.TRUE.equals(alertAction.getEnabled())) {
BatchEventProcessor<EventPubSub.ChangeEventHolder> processor = EventPubSub.addEventHandler(publisher);
publisher.setProcessor(processor);
LOG.info("Alert publisher started for {}", alert.getName());
} else {
// Only add alert that is enabled for publishing events
AlertActionStatus status =
new AlertActionStatus()
.withStatus(AlertActionStatus.Status.DISABLED)
.withTimestamp(System.currentTimeMillis())
.withFailureDetails(null);
alertAction.setStatusDetails(status);
}
Map<UUID, AlertsActionPublisher> alertsActionPublisherMap =
alertPublisherMap.get(alert.getId()) == null ? new HashMap<>() : alertPublisherMap.get(alert.getId());
@ -106,42 +104,56 @@ public class AlertsPublisherManager {
@SneakyThrows
public void updateAllAlertUsingAlertAction(AlertAction alertAction) {
List<CollectionDAO.EntityRelationshipRecord> records =
daoCollection
.relationshipDAO()
.findFrom(alertAction.getId().toString(), ALERT_ACTION, CONTAINS.ordinal(), ALERT);
EntityRepository<Alert> alertEntityRepository = Entity.getEntityRepository(ALERT);
for (CollectionDAO.EntityRelationshipRecord record : records) {
deleteAlertAllPublishers(record.getId());
Alert alert = alertEntityRepository.get(null, record.getId(), alertEntityRepository.getFields("*"));
addAlertActionPublisher(alert, alertAction);
List<AlertsActionPublisher> publishers = getAlertPublisherFromAlertAction(alertAction.getId());
// Avoid handling from DB
if (publishers.size() != 0) {
for (AlertsActionPublisher publisher : publishers) {
Alert alert = publisher.getAlert();
AlertAction action = publisher.getAlertAction();
deleteAlertAllPublishers(alert.getId());
if (action.getId().equals(alertAction.getId())) {
addAlertActionPublisher(alert, alertAction);
} else {
addAlertActionPublisher(alert, action);
}
}
}
}
public List<AlertsActionPublisher> getAlertPublisherFromAlertAction(UUID alertActionId) {
List<AlertsActionPublisher> publisherManagers = new ArrayList<>();
for (Map.Entry<UUID, Map<UUID, AlertsActionPublisher>> alertValues : alertPublisherMap.entrySet()) {
if (alertValues.getValue().containsKey(alertActionId)) {
publisherManagers.add(alertValues.getValue().get(alertActionId));
}
}
return publisherManagers;
}
@SneakyThrows
public void deleteAlertActionFromAllAlertPublisher(AlertAction alertAction) {
List<CollectionDAO.EntityRelationshipRecord> records =
daoCollection
.relationshipDAO()
.findFrom(alertAction.getId().toString(), ALERT_ACTION, CONTAINS.ordinal(), ALERT);
for (CollectionDAO.EntityRelationshipRecord record : records) {
deleteAlertActionPublisher(record.getId(), alertAction);
List<AlertsActionPublisher> publishers = getAlertPublisherFromAlertAction(alertAction.getId());
// Avoid handling from DB
if (publishers.size() != 0) {
for (AlertsActionPublisher alertsActionPublisher : publishers) {
if (alertsActionPublisher != null) {
deleteProcessorFromPubSub(alertsActionPublisher);
UUID alertId = alertsActionPublisher.getAlert().getId();
Map<UUID, AlertsActionPublisher> alertActionPublishersMap = alertPublisherMap.get(alertId);
alertActionPublishersMap.remove(alertAction.getId());
alertPublisherMap.put(alertId, alertActionPublishersMap);
}
}
}
}
public void deleteAlertActionPublisher(UUID alertId, AlertAction action) throws InterruptedException {
Map<UUID, AlertsActionPublisher> alertActionPublishers = alertPublisherMap.get(alertId);
if (alertActionPublishers != null) {
AlertsActionPublisher alertsActionPublisher = alertActionPublishers.get(action.getId());
if (alertsActionPublisher != null) {
alertsActionPublisher.getProcessor().halt();
alertsActionPublisher.awaitShutdown();
EventPubSub.removeProcessor(alertsActionPublisher.getProcessor());
LOG.info("Alert publisher deleted for {}", alertsActionPublisher.getAlert().getName());
alertActionPublishers.remove(action.getId());
alertPublisherMap.put(alertId, alertActionPublishers);
}
public void deleteProcessorFromPubSub(AlertsActionPublisher publisher) throws InterruptedException {
BatchEventProcessor<EventPubSub.ChangeEventHolder> processor = publisher.getProcessor();
if (processor != null) {
processor.halt();
publisher.awaitShutdown();
EventPubSub.removeProcessor(publisher.getProcessor());
LOG.info("Alert publisher deleted for {}", publisher.getAlert().getName());
}
}
@ -149,10 +161,7 @@ public class AlertsPublisherManager {
Map<UUID, AlertsActionPublisher> alertPublishers = alertPublisherMap.get(alertId);
if (alertPublishers != null) {
for (AlertsActionPublisher publisher : alertPublishers.values()) {
publisher.getProcessor().halt();
publisher.awaitShutdown();
EventPubSub.removeProcessor(publisher.getProcessor());
LOG.info("Alert publisher deleted for {}", publisher.getAlert().getName());
deleteProcessorFromPubSub(publisher);
}
alertPublisherMap.remove(alertId);
}

View File

@ -8,6 +8,7 @@ import static org.openmetadata.service.Entity.TEAM;
import static org.openmetadata.service.Entity.TEST_CASE;
import static org.openmetadata.service.Entity.USER;
import java.io.IOException;
import java.util.Set;
import java.util.UUID;
import lombok.extern.slf4j.Slf4j;
@ -20,8 +21,10 @@ import org.openmetadata.schema.tests.type.TestCaseStatus;
import org.openmetadata.schema.type.ChangeEvent;
import org.openmetadata.schema.type.EntityReference;
import org.openmetadata.schema.type.FieldChange;
import org.openmetadata.service.Entity;
import org.openmetadata.service.security.policyevaluator.SubjectCache;
import org.openmetadata.service.util.ChangeEventParser;
import org.openmetadata.service.util.JsonUtils;
@Slf4j
public class AlertsRuleEvaluator {
@ -67,11 +70,18 @@ public class AlertsRuleEvaluator {
description = "Returns true if the change event entity being accessed has following owners from the List.",
examples = {"matchAnyOwnerName('Owner1', 'Owner2')"},
paramInputType = SPECIFIC_INDEX_ELASTIC_SEARCH)
public boolean matchAnyOwnerName(String... ownerNameList) {
public boolean matchAnyOwnerName(String... ownerNameList) throws IOException {
if (changeEvent == null || changeEvent.getEntity() == null) {
return false;
}
EntityInterface entity = (EntityInterface) changeEvent.getEntity();
Class<? extends EntityInterface> entityClass = Entity.getEntityClassFromType(changeEvent.getEntityType());
EntityInterface entity;
if (changeEvent.getEntity() instanceof String) {
entity = JsonUtils.readValue((String) changeEvent.getEntity(), entityClass);
} else {
entity = JsonUtils.convertValue(changeEvent.getEntity(), entityClass);
}
EntityReference ownerReference = entity.getOwner();
if (ownerReference != null) {
if (USER.equals(ownerReference.getType())) {

View File

@ -275,6 +275,7 @@
"matchAnyOwnerName",
"matchAnyEntityFqn",
"matchAnyEventType",
"matchTestResult",
"matchUpdatedBy"
]
},
@ -284,6 +285,7 @@
"matchAnyOwnerName",
"matchAnyEntityFqn",
"matchAnyEventType",
"matchTestResult",
"matchUpdatedBy"
]
},

View File

@ -28,7 +28,6 @@ import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.HttpResponseException;
import org.awaitility.Awaitility;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInfo;
@ -55,7 +54,6 @@ import org.openmetadata.service.util.TestUtils;
@Slf4j
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
@Disabled
public class AlertResourceTest extends EntityResourceTest<Alert, CreateAlert> {
public static final TriggerConfig ALL_EVENTS_FILTER =
new TriggerConfig().withType(TriggerConfig.AlertTriggerType.ALL_DATA_ASSETS);
@ -100,8 +98,8 @@ public class AlertResourceTest extends EntityResourceTest<Alert, CreateAlert> {
// For the DISABLED Action Publisher are not available so it will have no status
AlertActionStatus status =
getStatus(alert.getId(), genericWebhookAction.getId(), Response.Status.NO_CONTENT.getStatusCode());
assertNull(status);
getStatus(alert.getId(), genericWebhookAction.getId(), Response.Status.OK.getStatusCode());
assertEquals(AlertActionStatus.Status.DISABLED, status.getStatus());
WebhookCallbackResource.EventDetails details = webhookCallbackResource.getEventDetails(webhookName);
assertNull(details);
//
@ -148,8 +146,8 @@ public class AlertResourceTest extends EntityResourceTest<Alert, CreateAlert> {
TestUtils.UpdateType.MINOR_UPDATE,
change);
AlertActionStatus status3 =
getStatus(alert.getId(), genericWebhookAction.getId(), Response.Status.NO_CONTENT.getStatusCode());
assertNull(status);
getStatus(alert.getId(), genericWebhookAction.getId(), Response.Status.OK.getStatusCode());
assertEquals(AlertActionStatus.Status.DISABLED, status3.getStatus());
int iterations = 0;
while (iterations < 10) {

View File

@ -29,6 +29,7 @@ import org.openmetadata.schema.type.TagLabel;
public interface EntityInterface {
// Lower case entity name to canonical entity name map
Map<String, String> CANONICAL_ENTITY_NAME_MAP = new HashMap<>();
Map<String, Class<? extends EntityInterface>> ENTITY_TYPE_TO_CLASS_MAP = new HashMap<>();
UUID getId();