use of com.github.ambry.rest.RestRequest in project ambry by linkedin.
the class SimpleAmbryCostModelPolicyTest method testCalculateRequestCost.
@Test
public void testCalculateRequestCost() throws Exception {
SimpleAmbryCostModelPolicy requestCostPolicy = new SimpleAmbryCostModelPolicy();
RestResponseChannel restResponseChannel = mock(RestResponseChannel.class);
when(restResponseChannel.getHeader(anyString())).thenReturn(0);
String blobUri = "/AAYIAQSSAAgAAQAAAAAAABpFymbGwe7sRBWYa5OPlkcNHQ.bin";
// test for a 4 MB GET request.
BlobInfo blobInfo = getBlobInfo(4 * MB);
RestRequest restRequest = createMockRequestWithMethod(RestMethod.GET, blobUri, -1);
Map<String, Double> costMap = requestCostPolicy.calculateRequestCost(restRequest, restResponseChannel, blobInfo);
verifyReadCost(costMap, 1);
// test for a small GET request (fractional CU).
blobInfo = getBlobInfo(6 * MB);
costMap = requestCostPolicy.calculateRequestCost(restRequest, restResponseChannel, blobInfo);
verifyReadCost(costMap, 2);
// test for a GET request of blob of size 0.
blobInfo = getBlobInfo(0);
restRequest = createMockRequestWithMethod(RestMethod.GET, blobUri, -1);
costMap = requestCostPolicy.calculateRequestCost(restRequest, restResponseChannel, blobInfo);
verifyReadCost(costMap, 1);
// test for a small POST request (fractional storage cost).
blobInfo = getBlobInfo(8 * MB);
restRequest = createMockRequestWithMethod(RestMethod.POST, blobUri, 8 * MB);
costMap = requestCostPolicy.calculateRequestCost(restRequest, restResponseChannel, blobInfo);
verifyWriteCost(costMap, 2, 8 * 1024 * 1024 / (double) QuotaUtils.BYTES_IN_GB);
// test for a large POST request.
blobInfo = getBlobInfo(4 * GB);
restRequest = createMockRequestWithMethod(RestMethod.POST, blobUri, 4 * GB);
costMap = requestCostPolicy.calculateRequestCost(restRequest, restResponseChannel, blobInfo);
verifyWriteCost(costMap, 1024, 4);
// test for a POST request of blob of size 0.
blobInfo = getBlobInfo(0);
restRequest = createMockRequestWithMethod(RestMethod.POST, blobUri, 0);
costMap = requestCostPolicy.calculateRequestCost(restRequest, restResponseChannel, blobInfo);
verifyWriteCost(costMap, 1, 0);
// test for a HEAD request.
restRequest = createMockRequestWithMethod(RestMethod.HEAD, blobUri, -1);
costMap = requestCostPolicy.calculateRequestCost(restRequest, restResponseChannel, blobInfo);
verifyReadCost(costMap, 1);
// test for a DELETE request.
restRequest = createMockRequestWithMethod(RestMethod.DELETE, blobUri, -1);
costMap = requestCostPolicy.calculateRequestCost(restRequest, restResponseChannel, blobInfo);
verifyWriteCost(costMap, 1, 0.0);
// test for a PUT request.
restRequest = createMockRequestWithMethod(RestMethod.PUT, blobUri, -1);
costMap = requestCostPolicy.calculateRequestCost(restRequest, restResponseChannel, blobInfo);
verifyWriteCost(costMap, 1, 0.0);
// test for PUT with null blob info.
costMap = requestCostPolicy.calculateRequestCost(restRequest, restResponseChannel, null);
verifyWriteCost(costMap, 1, 0.0);
// test BlobInfo and UserMetadata GET requests
blobInfo = getBlobInfo(40 * GB);
restRequest = createMockRequestWithMethod(RestMethod.GET, blobUri + "/BlobInfo", -1);
costMap = requestCostPolicy.calculateRequestCost(restRequest, restResponseChannel, blobInfo);
verifyReadCost(costMap, 1);
restRequest = createMockRequestWithMethod(RestMethod.GET, blobUri + "/UserMetadata", -1);
costMap = requestCostPolicy.calculateRequestCost(restRequest, restResponseChannel, blobInfo);
verifyReadCost(costMap, 1);
// Plain GET should use blob size
restRequest = createMockRequestWithMethod(RestMethod.GET, blobUri, -1);
costMap = requestCostPolicy.calculateRequestCost(restRequest, restResponseChannel, blobInfo);
verifyReadCost(costMap, 10240);
// TODO add a range request case with large range
}
use of com.github.ambry.rest.RestRequest in project ambry by linkedin.
the class TtlUpdateHandlerTest method badArgsTest.
/**
* Tests for expected failures with bad arguments
* @throws Exception
*/
private void badArgsTest() throws Exception {
RestRequest restRequest = new MockRestRequest(MockRestRequest.DUMMY_DATA, null);
restRequest.setArg(RestUtils.Headers.BLOB_ID, blobId);
// no service ID
verifyFailureWithErrorCode(restRequest, RestServiceErrorCode.MissingArgs);
restRequest = new MockRestRequest(MockRestRequest.DUMMY_DATA, null);
restRequest.setArg(RestUtils.Headers.SERVICE_ID, SERVICE_ID);
// no blob ID
verifyFailureWithErrorCode(restRequest, RestServiceErrorCode.MissingArgs);
restRequest = new MockRestRequest(MockRestRequest.DUMMY_DATA, null);
// not a valid blob ID
restRequest.setArg(RestUtils.Headers.BLOB_ID, "abcd");
idConverterFactory.translation = "abcd";
restRequest.setArg(RestUtils.Headers.SERVICE_ID, SERVICE_ID);
verifyFailureWithErrorCode(restRequest, RestServiceErrorCode.BadRequest);
}
use of com.github.ambry.rest.RestRequest in project ambry by linkedin.
the class HostLevelThrottlerTest method quotaTest.
/**
* Test to make sure {@link HostLevelThrottler#shouldThrottle(RestRequest)} works as expected.
*/
@Test
public void quotaTest() throws Exception {
Properties props = new Properties();
props.setProperty(HostThrottleConfig.REST_REQUEST_QUOTA_STRING, "{\"PUT\": \"20\",\"GET\": \"20\",\"POST\": \"20\",\"HEAD\": \"20\",\"OPTIONS\": \"20\",\"DELETE\": \"20\"}");
HostThrottleConfig hostThrottleConfig = new HostThrottleConfig(new VerifiableProperties(props));
MockClock clock = new MockClock();
HostLevelThrottler quotaManager = new HostLevelThrottler(createQuotaMock(hostThrottleConfig, clock), new HashMap<>(), null);
// Issue new requests. Since MockClock tick doesn't change, rate is 0.
for (int i = 0; i < 100; i++) {
for (RestMethod restMethod : RestMethod.values()) {
RestRequest restRequest = createRestRequest(restMethod, "http://www.linkedin.com/");
Assert.assertFalse("Should not throttle", quotaManager.shouldThrottle(restRequest));
}
}
// Move MockClock ahead to 5 seconds later. Rate = 20. New requests should be denied unless its quota is not defined.
clock.tick(5);
for (RestMethod restMethod : RestMethod.values()) {
RestRequest restRequest = createRestRequest(restMethod, "http://www.linkedin.com/");
if (restMethod == RestMethod.UNKNOWN) {
Assert.assertFalse("Should not throttle.", quotaManager.shouldThrottle(restRequest));
} else {
Assert.assertTrue("Should throttle", quotaManager.shouldThrottle(restRequest));
}
}
// Clock tick to another 5 seconds later, rate < 20. Accept new requests.
clock.tick(5);
for (RestMethod restMethod : RestMethod.values()) {
RestRequest restRequest = createRestRequest(restMethod, "http://www.linkedin.com/");
Assert.assertFalse("Should not throttle", quotaManager.shouldThrottle(restRequest));
}
}
use of com.github.ambry.rest.RestRequest in project ambry by linkedin.
the class FrontendRestRequestService method handlePut.
@Override
public void handlePut(RestRequest restRequest, RestResponseChannel restResponseChannel) {
ThrowingConsumer<RequestPath> routingAction = requestPath -> {
if (requestPath.matchesOperation(Operations.UPDATE_TTL)) {
ttlUpdateHandler.handle(restRequest, restResponseChannel, (r, e) -> {
if (e instanceof RouterException && ((RouterException) e).getErrorCode() == RouterErrorCode.BlobUpdateNotAllowed) {
restResponseChannel.setHeader(Headers.ALLOW, TTL_UPDATE_REJECTED_ALLOW_HEADER_VALUE);
}
submitResponse(restRequest, restResponseChannel, null, e);
});
} else if (requestPath.matchesOperation(Operations.UNDELETE) && frontendConfig.enableUndelete) {
// If the undelete is not enabled, then treat it as unrecognized operation.
// And always send failure reason back to client for undelete
restRequest.setArg(SEND_FAILURE_REASON, Boolean.TRUE);
undeleteHandler.handle(restRequest, restResponseChannel, (r, e) -> {
submitResponse(restRequest, restResponseChannel, null, e);
});
} else if (requestPath.matchesOperation(Operations.NAMED_BLOB)) {
restRequest.setArg(SEND_FAILURE_REASON, Boolean.TRUE);
namedBlobPutHandler.handle(restRequest, restResponseChannel, (r, e) -> submitResponse(restRequest, restResponseChannel, null, e));
} else {
throw new RestServiceException("Unrecognized operation: " + requestPath.getOperationOrBlobId(false), RestServiceErrorCode.BadRequest);
}
};
preProcessAndRouteRequest(restRequest, restResponseChannel, frontendMetrics.putPreProcessingMetrics, routingAction);
}
use of com.github.ambry.rest.RestRequest in project ambry by linkedin.
the class AmbryCUQuotaEnforcerTest method testCharge.
@Test
public void testCharge() throws Exception {
Container container = ACCOUNT.getAllContainers().iterator().next();
Map<QuotaName, Double> readRequestCostMap = Collections.singletonMap(QuotaName.READ_CAPACITY_UNIT, 9.0);
Map<QuotaName, Double> writeRequestCostMap = Collections.singletonMap(QuotaName.WRITE_CAPACITY_UNIT, 9.0);
Map<String, CapacityUnit> usageMap = QUOTA_SOURCE.getAllQuotaUsage();
// 1. Test that usage is updated and recommendation is serve when usage is within limit.
RestRequest restRequest = QuotaTestUtils.createRestRequest(ACCOUNT, container, RestMethod.GET);
AMBRY_QUOTA_ENFORCER.charge(restRequest, readRequestCostMap);
QuotaRecommendation quotaRecommendation = AMBRY_QUOTA_ENFORCER.recommend(restRequest);
assertEquals(quotaRecommendation.getQuotaName(), QuotaName.READ_CAPACITY_UNIT);
assertEquals(quotaRecommendation.getQuotaUsagePercentage(), 90, 0.1);
assertEquals(quotaRecommendation.getQuotaAction(), QuotaAction.ALLOW);
// make sure that correct quota is charged.
assertEquals(usageMap.get(String.valueOf(ACCOUNT.getId())).getWcu(), 0);
restRequest = QuotaTestUtils.createRestRequest(ACCOUNT, container, RestMethod.POST);
AMBRY_QUOTA_ENFORCER.charge(restRequest, writeRequestCostMap);
quotaRecommendation = AMBRY_QUOTA_ENFORCER.recommend(restRequest);
assertEquals(quotaRecommendation.getQuotaName(), QuotaName.WRITE_CAPACITY_UNIT);
assertEquals(quotaRecommendation.getQuotaUsagePercentage(), 90, 0.1);
assertEquals(quotaRecommendation.getQuotaAction(), QuotaAction.ALLOW);
// make sure that correct quota is charged.
assertEquals(usageMap.get(String.valueOf(ACCOUNT.getId())).getRcu(), 9);
// 2. Test that retryable quota exception is thrown when quota not found.
Account newAccount = ACCOUNT_SERVICE.generateRandomAccount(QuotaResourceType.ACCOUNT);
restRequest = QuotaTestUtils.createRestRequest(newAccount, newAccount.getAllContainers().iterator().next(), RestMethod.GET);
try {
AMBRY_QUOTA_ENFORCER.charge(restRequest, readRequestCostMap);
AMBRY_QUOTA_ENFORCER.recommend(restRequest);
fail("if quota is not found we should see exception");
} catch (QuotaException quotaException) {
Assert.assertTrue(quotaException.isRetryable());
}
// 3. Test that retryable quota exception is thrown in case of any error.
restRequest = QuotaTestUtils.createRestRequest(ACCOUNT, container, RestMethod.GET);
QUOTA_SOURCE.throwException = true;
try {
AMBRY_QUOTA_ENFORCER.charge(restRequest, readRequestCostMap);
fail("QuotaException should be thrown in case of any error.");
} catch (QuotaException quotaException) {
Assert.assertTrue(quotaException.isRetryable());
}
QUOTA_SOURCE.throwException = false;
// 4. Test that usage is updated and recommendation is deny when usage >= quota.
AMBRY_QUOTA_ENFORCER.charge(restRequest, readRequestCostMap);
quotaRecommendation = AMBRY_QUOTA_ENFORCER.recommend(restRequest);
assertEquals(QuotaName.READ_CAPACITY_UNIT, quotaRecommendation.getQuotaName());
assertEquals(180, quotaRecommendation.getQuotaUsagePercentage(), 0.1);
assertEquals(quotaRecommendation.getQuotaAction(), QuotaAction.DELAY);
// make sure that correct quota is charged.
assertEquals(9, usageMap.get(String.valueOf(ACCOUNT.getId())).getWcu());
assertEquals(18, // make sure that correct quota is charged.
usageMap.get(String.valueOf(ACCOUNT.getId())).getRcu());
restRequest = QuotaTestUtils.createRestRequest(ACCOUNT, container, RestMethod.POST);
AMBRY_QUOTA_ENFORCER.charge(restRequest, writeRequestCostMap);
quotaRecommendation = AMBRY_QUOTA_ENFORCER.recommend(restRequest);
assertEquals(QuotaName.WRITE_CAPACITY_UNIT, quotaRecommendation.getQuotaName());
assertEquals(180, quotaRecommendation.getQuotaUsagePercentage(), 0.1);
assertEquals(quotaRecommendation.getQuotaAction(), QuotaAction.DELAY);
assertEquals(18, // make sure that correct quota is charged.
usageMap.get(String.valueOf(ACCOUNT.getId())).getWcu());
assertEquals(18, // make sure that correct quota is charged.
usageMap.get(String.valueOf(ACCOUNT.getId())).getRcu());
restRequest = QuotaTestUtils.createRestRequest(ACCOUNT, container, RestMethod.DELETE);
AMBRY_QUOTA_ENFORCER.charge(restRequest, writeRequestCostMap);
quotaRecommendation = AMBRY_QUOTA_ENFORCER.recommend(restRequest);
assertEquals(QuotaName.WRITE_CAPACITY_UNIT, quotaRecommendation.getQuotaName());
assertEquals(270, quotaRecommendation.getQuotaUsagePercentage(), 0.1);
assertEquals(quotaRecommendation.getQuotaAction(), QuotaAction.DELAY);
assertEquals(27, // make sure that correct quota is charged.
usageMap.get(String.valueOf(ACCOUNT.getId())).getWcu());
assertEquals(18, // make sure that correct quota is charged.
usageMap.get(String.valueOf(ACCOUNT.getId())).getRcu());
restRequest = QuotaTestUtils.createRestRequest(ACCOUNT, container, RestMethod.PUT);
AMBRY_QUOTA_ENFORCER.charge(restRequest, writeRequestCostMap);
quotaRecommendation = AMBRY_QUOTA_ENFORCER.recommend(restRequest);
assertEquals(QuotaName.WRITE_CAPACITY_UNIT, quotaRecommendation.getQuotaName());
assertEquals(360, quotaRecommendation.getQuotaUsagePercentage(), 0.1);
assertEquals(quotaRecommendation.getQuotaAction(), QuotaAction.DELAY);
assertEquals(36, // make sure that correct quota is charged.
usageMap.get(String.valueOf(ACCOUNT.getId())).getWcu());
assertEquals(18, // make sure that correct quota is charged.
usageMap.get(String.valueOf(ACCOUNT.getId())).getRcu());
}
Aggregations