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

rongr pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pinot.git


The following commit(s) were added to refs/heads/master by this push:
     new 2f0eee9f12 Add health/readiness and health/liveness endpoint (#9031)
2f0eee9f12 is described below

commit 2f0eee9f1205f5119c940e1cd33bf31e8093347a
Author: Rong Rong <walterddr.walter...@gmail.com>
AuthorDate: Mon Jul 25 07:33:39 2022 -0700

    Add health/readiness and health/liveness endpoint (#9031)
    
    * add liveness and readiness endpoint
    
    Co-authored-by: Rong Rong <ro...@startree.ai>
    Co-authored-by: Xiaotian (Jackie) Jiang 
<17555551+jackie-ji...@users.noreply.github.com>
---
 .../server/api/resources/HealthCheckResource.java  | 31 +++++++++++-
 .../apache/pinot/server/api/BaseResourceTest.java  |  5 +-
 .../pinot/server/api/HealthCheckResourceTest.java  | 57 ++++++++++++++++++++++
 3 files changed, 90 insertions(+), 3 deletions(-)

diff --git 
a/pinot-server/src/main/java/org/apache/pinot/server/api/resources/HealthCheckResource.java
 
b/pinot-server/src/main/java/org/apache/pinot/server/api/resources/HealthCheckResource.java
index 921117382a..3157e7e456 100644
--- 
a/pinot-server/src/main/java/org/apache/pinot/server/api/resources/HealthCheckResource.java
+++ 
b/pinot-server/src/main/java/org/apache/pinot/server/api/resources/HealthCheckResource.java
@@ -55,7 +55,36 @@ public class HealthCheckResource {
       @ApiResponse(code = 503, message = "Server is not healthy")
   })
   public String checkHealth() {
-    Status status = ServiceStatus.getServiceStatus(_instanceId);
+    return getReadinessStatus(_instanceId);
+  }
+
+  @GET
+  @Path("/health/liveness")
+  @Produces(MediaType.TEXT_PLAIN)
+  @ApiOperation(value = "Checking server liveness status.")
+  @ApiResponses(value = {
+      @ApiResponse(code = 200, message = "Server is live"),
+      @ApiResponse(code = 503, message = "Server is not live")
+  })
+  public String checkLiveness() {
+    // Returns OK since if we reached here, the admin application is running.
+    return "OK";
+  }
+
+  @GET
+  @Path("/health/readiness")
+  @Produces(MediaType.TEXT_PLAIN)
+  @ApiOperation(value = "Checking server readiness status")
+  @ApiResponses(value = {
+      @ApiResponse(code = 200, message = "Server is ready to serve queries"),
+      @ApiResponse(code = 503, message = "Server is not ready to serve 
queries")
+  })
+  public String checkReadiness() {
+    return getReadinessStatus(_instanceId);
+  }
+
+  private static String getReadinessStatus(String instanceId) throws 
WebApplicationException {
+    Status status = ServiceStatus.getServiceStatus(instanceId);
     if (status == Status.GOOD) {
       return "OK";
     }
diff --git 
a/pinot-server/src/test/java/org/apache/pinot/server/api/BaseResourceTest.java 
b/pinot-server/src/test/java/org/apache/pinot/server/api/BaseResourceTest.java
index d9a88d504f..c0ad22a2dc 100644
--- 
a/pinot-server/src/test/java/org/apache/pinot/server/api/BaseResourceTest.java
+++ 
b/pinot-server/src/test/java/org/apache/pinot/server/api/BaseResourceTest.java
@@ -87,6 +87,7 @@ public abstract class BaseResourceTest {
   private File _avroFile;
   private AdminApiApplication _adminApiApplication;
   protected WebTarget _webTarget;
+  protected String _instanceId;
 
   @SuppressWarnings("SuspiciousMethodCalls")
   @BeforeClass
@@ -133,8 +134,8 @@ public abstract class BaseResourceTest {
             ? NetUtils.getHostnameOrAddress() : NetUtils.getHostAddress());
     int port = 
serverConf.getProperty(CommonConstants.Helix.KEY_OF_SERVER_NETTY_PORT,
         CommonConstants.Helix.DEFAULT_SERVER_NETTY_PORT);
-    serverConf.setProperty(CommonConstants.Server.CONFIG_OF_INSTANCE_ID,
-        CommonConstants.Helix.PREFIX_OF_SERVER_INSTANCE + hostname + "_" + 
port);
+    _instanceId = CommonConstants.Helix.PREFIX_OF_SERVER_INSTANCE + hostname + 
"_" + port;
+    serverConf.setProperty(CommonConstants.Server.CONFIG_OF_INSTANCE_ID, 
_instanceId);
     _adminApiApplication = new AdminApiApplication(serverInstance, new 
AllowAllAccessFactory(), serverConf);
     _adminApiApplication.start(Collections.singletonList(
         new ListenerConfig(CommonConstants.HTTP_PROTOCOL, "0.0.0.0", 
CommonConstants.Server.DEFAULT_ADMIN_API_PORT,
diff --git 
a/pinot-server/src/test/java/org/apache/pinot/server/api/HealthCheckResourceTest.java
 
b/pinot-server/src/test/java/org/apache/pinot/server/api/HealthCheckResourceTest.java
new file mode 100644
index 0000000000..8d8e1b6b46
--- /dev/null
+++ 
b/pinot-server/src/test/java/org/apache/pinot/server/api/HealthCheckResourceTest.java
@@ -0,0 +1,57 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.pinot.server.api;
+
+import javax.ws.rs.core.Response;
+import org.apache.pinot.common.utils.ServiceStatus;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+
+public class HealthCheckResourceTest extends BaseResourceTest {
+  @Test
+  public void checkHealthProbes()
+      throws Exception {
+    String healthPath = "/health";
+    String livenessPath = "/health/liveness";
+    String readinessPath = "/health/readiness";
+
+    ServiceStatus.ServiceStatusCallback mockSuccessCallback = 
mock(ServiceStatus.ServiceStatusCallback.class);
+    ServiceStatus.ServiceStatusCallback mockFailureCallback = 
mock(ServiceStatus.ServiceStatusCallback.class);
+    
when(mockSuccessCallback.getServiceStatus()).thenReturn(ServiceStatus.Status.GOOD);
+    
when(mockFailureCallback.getServiceStatus()).thenReturn(ServiceStatus.Status.BAD);
+
+    
Assert.assertEquals(_webTarget.path(livenessPath).request().get(Response.class).getStatus(),
 200);
+    
Assert.assertEquals(_webTarget.path(healthPath).request().get(Response.class).getStatus(),
 503);
+    
Assert.assertEquals(_webTarget.path(readinessPath).request().get(Response.class).getStatus(),
 503);
+
+    ServiceStatus.setServiceStatusCallback(_instanceId, mockSuccessCallback);
+    
Assert.assertEquals(_webTarget.path(livenessPath).request().get(Response.class).getStatus(),
 200);
+    
Assert.assertEquals(_webTarget.path(healthPath).request().get(Response.class).getStatus(),
 200);
+    
Assert.assertEquals(_webTarget.path(readinessPath).request().get(Response.class).getStatus(),
 200);
+
+    ServiceStatus.setServiceStatusCallback(_instanceId, mockFailureCallback);
+    
Assert.assertEquals(_webTarget.path(livenessPath).request().get(Response.class).getStatus(),
 200);
+    
Assert.assertEquals(_webTarget.path(healthPath).request().get(Response.class).getStatus(),
 503);
+    
Assert.assertEquals(_webTarget.path(readinessPath).request().get(Response.class).getStatus(),
 503);
+  }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@pinot.apache.org
For additional commands, e-mail: commits-h...@pinot.apache.org

Reply via email to