ATLAS-4826: Provide Liveness and Readyness probes in Atlas
Signed-off-by: Pinal Shah <pinal.shah@freestoneinfotech.com>
diff --git a/repository/src/main/java/org/apache/atlas/util/AtlasMetricsUtil.java b/repository/src/main/java/org/apache/atlas/util/AtlasMetricsUtil.java
index beb90e6..a13e073 100644
--- a/repository/src/main/java/org/apache/atlas/util/AtlasMetricsUtil.java
+++ b/repository/src/main/java/org/apache/atlas/util/AtlasMetricsUtil.java
@@ -236,6 +236,14 @@
return true;
}
+ public boolean isBackendStoreActive(){
+ return getBackendStoreStatus();
+ }
+
+ public boolean isIndexStoreActive(){
+ return getIndexStoreStatus();
+ }
+
private void runWithTimeout(final Runnable runnable, long timeout, TimeUnit timeUnit) throws Exception {
runWithTimeout(new Callable<Object>() {
@Override
diff --git a/webapp/src/main/java/org/apache/atlas/web/resources/AdminResource.java b/webapp/src/main/java/org/apache/atlas/web/resources/AdminResource.java
index 4d59fa3..27ec59d 100755
--- a/webapp/src/main/java/org/apache/atlas/web/resources/AdminResource.java
+++ b/webapp/src/main/java/org/apache/atlas/web/resources/AdminResource.java
@@ -23,6 +23,7 @@
import org.apache.atlas.AtlasClient;
import org.apache.atlas.AtlasConfiguration;
import org.apache.atlas.AtlasErrorCode;
+import org.apache.atlas.AtlasException;
import org.apache.atlas.authorize.AtlasAdminAccessRequest;
import org.apache.atlas.authorize.AtlasAuthorizationUtils;
import org.apache.atlas.authorize.AtlasEntityAccessRequest;
@@ -67,6 +68,7 @@
import org.apache.atlas.tasks.TaskManagement;
import org.apache.atlas.type.AtlasType;
import org.apache.atlas.type.AtlasTypeRegistry;
+import org.apache.atlas.util.AtlasMetricsUtil;
import org.apache.atlas.util.SearchTracker;
import org.apache.atlas.utils.AtlasJson;
import org.apache.atlas.utils.AtlasPerfTracer;
@@ -188,6 +190,7 @@
private final boolean isTasksEnabled;
private final boolean isOnDemandLineageEnabled;
private final int defaultLineageNodeCount;
+ private final AtlasMetricsUtil atlasMetricsUtil;
private AtlasAuditReductionService auditReductionService;
@@ -206,7 +209,7 @@
AtlasServerService serverService,
ExportImportAuditService exportImportAuditService, AtlasEntityStore entityStore,
AtlasPatchManager patchManager, AtlasAuditService auditService, EntityAuditRepository auditRepository,
- TaskManagement taskManagement, AtlasDebugMetricsSink debugMetricsRESTSink, AtlasAuditReductionService atlasAuditReductionService) {
+ TaskManagement taskManagement, AtlasDebugMetricsSink debugMetricsRESTSink, AtlasAuditReductionService atlasAuditReductionService, AtlasMetricsUtil atlasMetricsUtil) {
this.serviceState = serviceState;
this.metricsService = metricsService;
this.exportService = exportService;
@@ -224,6 +227,7 @@
this.taskManagement = taskManagement;
this.debugMetricsRESTSink = debugMetricsRESTSink;
this.auditReductionService = atlasAuditReductionService;
+ this.atlasMetricsUtil = atlasMetricsUtil;
if (atlasProperties != null) {
this.defaultUIVersion = atlasProperties.getString(DEFAULT_UI_VERSION, UI_VERSION_V2);
@@ -1111,4 +1115,44 @@
}
}
+ /**
+ * API to indicate service liveness
+ * @return response payload as json
+ * @throws AtlasBaseException
+ * @HTTP 200 if Atlas is alive
+ * @HTTP 500 if Atlas is not alive and requires a restart
+ */
+ @GET
+ @Path("/liveness")
+ public Response serviceLiveliness() throws AtlasBaseException {
+
+ if (serviceState.getState() == ServiceState.ServiceStateValue.ACTIVE || serviceState.getState() == ServiceState.ServiceStateValue.MIGRATING) {
+ return Response.status(Response.Status.OK).entity("Service is live").build();
+ } else {
+ LOG.error("Atlas Service is not live");
+ throw new AtlasBaseException(AtlasErrorCode.INTERNAL_ERROR, "Atlas Service is not live");
+ }
+ }
+
+ /**
+ * API to indicate service readiness
+ * @return response payload as json
+ * @throws AtlasBaseException
+ * @HTTP 200 if Atlas is alive and ready to accept client requests
+ * @HTTP 500 if Atlas is either not alive or not ready to accept client requests
+ */
+ @GET
+ @Path("/readiness")
+ public Response serviceReadiness() throws AtlasBaseException {
+
+ if((serviceState.getState() == ServiceState.ServiceStateValue.ACTIVE) &&
+ (atlasMetricsUtil.isIndexStoreActive() && atlasMetricsUtil.isBackendStoreActive())) {
+ return Response.status(Response.Status.OK).entity("Service is ready to accept requests").build();
+ }
+ else {
+ LOG.error("Service is not ready to accept client requests");
+ throw new AtlasBaseException(AtlasErrorCode.INTERNAL_ERROR, "Service not ready to accept client requests");
+ }
+ }
+
}
diff --git a/webapp/src/test/java/org/apache/atlas/web/resources/AdminResourceTest.java b/webapp/src/test/java/org/apache/atlas/web/resources/AdminResourceTest.java
index 5b16ba1..268fca7 100644
--- a/webapp/src/test/java/org/apache/atlas/web/resources/AdminResourceTest.java
+++ b/webapp/src/test/java/org/apache/atlas/web/resources/AdminResourceTest.java
@@ -51,7 +51,7 @@
when(serviceState.getState()).thenReturn(ServiceState.ServiceStateValue.ACTIVE);
- AdminResource adminResource = new AdminResource(serviceState, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null);
+ AdminResource adminResource = new AdminResource(serviceState, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null);
Response response = adminResource.getStatus();
assertEquals(response.getStatus(), HttpServletResponse.SC_OK);
JsonNode entity = AtlasJson.parseToV1JsonNode((String) response.getEntity());
@@ -62,7 +62,7 @@
public void testResourceGetsValueFromServiceState() throws IOException {
when(serviceState.getState()).thenReturn(ServiceState.ServiceStateValue.PASSIVE);
- AdminResource adminResource = new AdminResource(serviceState, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null);
+ AdminResource adminResource = new AdminResource(serviceState, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null);
Response response = adminResource.getStatus();
verify(serviceState).getState();