-
Notifications
You must be signed in to change notification settings - Fork 91
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
208 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
16 changes: 16 additions & 0 deletions
16
...-controller/src/main/java/com/linkedin/venice/controller/ParentControllerRegionState.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package com.linkedin.venice.controller; | ||
|
||
/** | ||
* Enum representing the state of the region where the parent controller resides. | ||
* (i.e., Region dc-0 is ACTIVE while Region dc-1 is PASSIVE | ||
* This means that ParentController in dc-0 is serving requests while ParentController in dc-1 is rejecting requests) | ||
*/ | ||
public enum ParentControllerRegionState { | ||
/** The region is active, so the parent controller in the region is serving requests */ | ||
ACTIVE, | ||
/** | ||
* The region is passive, so the parent controller in the region is rejecting requests. | ||
* This region is ready to take over if components in the currently active region fails | ||
*/ | ||
PASSIVE | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
43 changes: 43 additions & 0 deletions
43
.../java/com/linkedin/venice/controller/server/VeniceParentControllerRegionStateHandler.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
package com.linkedin.venice.controller.server; | ||
|
||
import static com.linkedin.venice.controller.ParentControllerRegionState.ACTIVE; | ||
|
||
import com.linkedin.venice.HttpConstants; | ||
import com.linkedin.venice.controller.Admin; | ||
import com.linkedin.venice.controller.ParentControllerRegionState; | ||
import com.linkedin.venice.controllerapi.ControllerResponse; | ||
import com.linkedin.venice.exceptions.ErrorType; | ||
import spark.Request; | ||
import spark.Response; | ||
import spark.Route; | ||
|
||
|
||
/** | ||
* Handler for checking the state of the region of the parent controller to handle requests in its region. | ||
*/ | ||
public class VeniceParentControllerRegionStateHandler implements Route { | ||
public static final String ACTIVE_CHECK_FAILURE_WARN_MESSAGE_PREFIX = | ||
"Only active parent controllers are allowed to run "; | ||
private Admin admin; | ||
private Route route; | ||
|
||
public VeniceParentControllerRegionStateHandler(Admin admin, Route route) { | ||
this.admin = admin; | ||
this.route = route; | ||
} | ||
|
||
@Override | ||
public Object handle(Request request, Response response) throws Exception { | ||
ParentControllerRegionState parentControllerRegionState = admin.getParentControllerRegionState(); | ||
boolean isParent = admin.isParent(); | ||
if (isParent && parentControllerRegionState != ACTIVE) { | ||
ControllerResponse responseObject = new ControllerResponse(); | ||
response.type(HttpConstants.JSON); | ||
response.status(HttpConstants.SC_MISDIRECTED_REQUEST); | ||
responseObject.setError(ACTIVE_CHECK_FAILURE_WARN_MESSAGE_PREFIX + request.url()); | ||
responseObject.setErrorType(ErrorType.INCORRECT_CONTROLLER); | ||
return AdminSparkServer.OBJECT_MAPPER.writeValueAsString(responseObject); | ||
} | ||
return route.handle(request, response); | ||
} | ||
} |
102 changes: 102 additions & 0 deletions
102
...a/com/linkedin/venice/controller/server/TestVeniceParentControllerRegionStateHandler.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
package com.linkedin.venice.controller.server; | ||
|
||
import static com.linkedin.venice.controller.ParentControllerRegionState.ACTIVE; | ||
import static com.linkedin.venice.controller.ParentControllerRegionState.PASSIVE; | ||
import static com.linkedin.venice.controller.server.VeniceParentControllerRegionStateHandler.ACTIVE_CHECK_FAILURE_WARN_MESSAGE_PREFIX; | ||
import static org.mockito.Mockito.mock; | ||
import static org.mockito.Mockito.never; | ||
import static org.mockito.Mockito.reset; | ||
import static org.mockito.Mockito.verify; | ||
import static org.mockito.Mockito.when; | ||
|
||
import com.linkedin.venice.HttpConstants; | ||
import com.linkedin.venice.controller.Admin; | ||
import com.linkedin.venice.controllerapi.ControllerResponse; | ||
import com.linkedin.venice.exceptions.ErrorType; | ||
import com.linkedin.venice.exceptions.ExceptionType; | ||
import com.linkedin.venice.utils.ObjectMapperFactory; | ||
import org.apache.logging.log4j.LogManager; | ||
import org.apache.logging.log4j.Logger; | ||
import org.testng.Assert; | ||
import org.testng.annotations.Test; | ||
import spark.Request; | ||
import spark.Response; | ||
import spark.Route; | ||
|
||
|
||
public class TestVeniceParentControllerRegionStateHandler { | ||
private Logger logger = LogManager.getLogger(TestVeniceParentControllerRegionStateHandler.class); | ||
private Admin admin = mock(Admin.class); | ||
private Request request = mock(Request.class); | ||
private Response response = mock(Response.class); | ||
private VeniceRouteHandler<ControllerResponse> veniceRouteHandler = | ||
new VeniceRouteHandler<ControllerResponse>(ControllerResponse.class) { | ||
@Override | ||
public void internalHandle(Request request, ControllerResponse veniceResponse) { | ||
logger.info("VeniceParentControllerRegionStateHandler is working"); | ||
veniceResponse.setName("working test response"); | ||
veniceResponse.setCluster("working test cluster"); | ||
} | ||
}; | ||
|
||
@Test | ||
public void testActiveParent() throws Exception { | ||
reset(admin, request, response); | ||
when(admin.getParentControllerRegionState()).thenReturn(ACTIVE); | ||
when(admin.isParent()).thenReturn(true); | ||
Assert.assertEquals(admin.getParentControllerRegionState(), ACTIVE); | ||
Assert.assertTrue(admin.isParent()); | ||
verifySuccessResponse(response); | ||
} | ||
|
||
@Test | ||
public void testPassiveParent() throws Exception { | ||
reset(admin, request, response); | ||
when(admin.getParentControllerRegionState()).thenReturn(PASSIVE); | ||
when(admin.isParent()).thenReturn(true); | ||
Assert.assertEquals(admin.getParentControllerRegionState(), PASSIVE); | ||
Assert.assertTrue(admin.isParent()); | ||
verifyErrorResponse(response); | ||
} | ||
|
||
@Test | ||
public void testActiveChild() throws Exception { | ||
reset(admin, request, response); | ||
when(admin.getParentControllerRegionState()).thenReturn(ACTIVE); | ||
when(admin.isParent()).thenReturn(false); | ||
Assert.assertEquals(admin.getParentControllerRegionState(), ACTIVE); | ||
Assert.assertFalse(admin.isParent()); | ||
verifySuccessResponse(response); | ||
} | ||
|
||
@Test | ||
public void testPassiveChild() throws Exception { | ||
reset(admin, request, response); | ||
when(admin.getParentControllerRegionState()).thenReturn(PASSIVE); | ||
when(admin.isParent()).thenReturn(false); | ||
Assert.assertEquals(admin.getParentControllerRegionState(), PASSIVE); | ||
Assert.assertFalse(admin.isParent()); | ||
verifySuccessResponse(response); | ||
} | ||
|
||
private void verifySuccessResponse(Response response) throws Exception { | ||
Route route = new VeniceParentControllerRegionStateHandler(admin, veniceRouteHandler); | ||
String veniceResponseStr = route.handle(request, response).toString(); | ||
verify(response, never()).status(HttpConstants.SC_MISDIRECTED_REQUEST); | ||
ControllerResponse veniceResponse = | ||
ObjectMapperFactory.getInstance().readValue(veniceResponseStr, ControllerResponse.class); | ||
Assert.assertEquals(veniceResponse.getName(), "working test response"); | ||
Assert.assertEquals(veniceResponse.getCluster(), "working test cluster"); | ||
} | ||
|
||
private void verifyErrorResponse(Response response) throws Exception { | ||
Route route = new VeniceParentControllerRegionStateHandler(admin, veniceRouteHandler); | ||
String veniceResponseStr = route.handle(request, response).toString(); | ||
ControllerResponse veniceResponse = | ||
ObjectMapperFactory.getInstance().readValue(veniceResponseStr, ControllerResponse.class); | ||
verify(response).status(HttpConstants.SC_MISDIRECTED_REQUEST); | ||
Assert.assertTrue(veniceResponse.getError().startsWith(ACTIVE_CHECK_FAILURE_WARN_MESSAGE_PREFIX)); | ||
Assert.assertEquals(veniceResponse.getErrorType(), ErrorType.INCORRECT_CONTROLLER); | ||
Assert.assertEquals(veniceResponse.getExceptionType(), ExceptionType.INCORRECT_CONTROLLER); | ||
} | ||
} |