use of com.linkedin.restli.common.UpdateEntityStatus in project rest.li by linkedin.
the class TestBatchPartialUpdateResponseBuilder method testBuilder.
/**
* Ensures that the response builder can correctly process inputs without any errors. This involves varying result
* types, status codes, and values of the {@link com.linkedin.restli.common.RestConstants#RETURN_ENTITY_PARAM} query
* parameter.
*
* @param result result object to use as input to this builder.
* @param isReturnEntityRequested semantic value of the "return entity" query parameter.
* @param expectedRecords expected records in response data, if any.
*/
@Test(dataProvider = "responseData")
@SuppressWarnings("unchecked")
public void testBuilder(BatchUpdateResult<Long, TestRecord> result, boolean isReturnEntityRequested, Map<?, RecordTemplate> expectedRecords) {
Map<String, String> headers = ResponseBuilderUtil.getHeaders();
RoutingResult routingResult = getMockRoutingResult(isReturnEntityRequested, null);
BatchPartialUpdateResponseBuilder batchPartialUpdateResponseBuilder = new BatchPartialUpdateResponseBuilder(new ErrorResponseBuilder());
RestLiResponseData<BatchPartialUpdateResponseEnvelope> responseData = batchPartialUpdateResponseBuilder.buildRestLiResponseData(null, routingResult, result, headers, Collections.emptyList());
RestLiResponse restLiResponse = batchPartialUpdateResponseBuilder.buildResponse(routingResult, responseData);
ResponseBuilderUtil.validateHeaders(restLiResponse, headers);
Assert.assertEquals(restLiResponse.getStatus(), HttpStatus.S_200_OK);
Assert.assertEquals(responseData.getResponseType(), ResponseType.BATCH_ENTITIES);
Assert.assertEquals(responseData.getResourceMethod(), ResourceMethod.BATCH_PARTIAL_UPDATE);
Assert.assertEquals(responseData.getResponseEnvelope().getResourceMethod(), ResourceMethod.BATCH_PARTIAL_UPDATE);
final Map<Long, BatchResponseEnvelope.BatchResponseEntry> batchResponseMap = (Map<Long, BatchResponseEnvelope.BatchResponseEntry>) responseData.getResponseEnvelope().getBatchResponseMap();
Assert.assertNotNull(batchResponseMap);
for (Map.Entry<Long, BatchResponseEnvelope.BatchResponseEntry> entry : batchResponseMap.entrySet()) {
final HttpStatus expectedStatus = result.getResults().get(entry.getKey()).getStatus();
BatchResponseEnvelope.BatchResponseEntry batchResponseEntry = entry.getValue();
Assert.assertNotNull(batchResponseEntry);
Assert.assertFalse(batchResponseEntry.hasException());
Assert.assertEquals(batchResponseEntry.getStatus(), expectedStatus);
UpdateStatus updateStatus = (UpdateStatus) batchResponseEntry.getRecord();
Assert.assertNotNull(updateStatus);
Assert.assertFalse(updateStatus.hasError());
Assert.assertEquals(updateStatus.getStatus().intValue(), expectedStatus.getCode());
if (updateStatus instanceof UpdateEntityStatus) {
UpdateEntityStatus<TestRecord> updateEntityStatus = (UpdateEntityStatus<TestRecord>) updateStatus;
Assert.assertEquals(updateEntityStatus.hasEntity(), isReturnEntityRequested);
// If no entity is to be returned, then these should both be null
RecordTemplate record = updateEntityStatus.getEntity();
// can be null
RecordTemplate expectedRecord = expectedRecords.get(entry.getKey());
Assert.assertEquals(record, expectedRecord);
}
}
}
use of com.linkedin.restli.common.UpdateEntityStatus in project rest.li by linkedin.
the class TestBatchPartialUpdateResponseBuilder method testProjectionInBuildRestLiResponseData.
/**
* Ensures that the returned entities are properly projected when a projection mask is passed into the response builder.
*/
@Test
@SuppressWarnings("unchecked")
public void testProjectionInBuildRestLiResponseData() {
final Long id = 1L;
TestRecord record = new TestRecord().setIntField(2147).setDoubleField(21.47).setFloatField(123F).setLongField(456L);
BatchUpdateEntityResult<Long, TestRecord> result = new BatchUpdateEntityResult<>(Collections.singletonMap(id, new UpdateEntityResponse<>(HttpStatus.S_200_OK, record)));
MaskTree maskTree = new MaskTree();
maskTree.addOperation(new PathSpec("intField"), MaskOperation.POSITIVE_MASK_OP);
Map<String, String> headers = ResponseBuilderUtil.getHeaders();
RoutingResult routingResult = getMockRoutingResult(true, maskTree);
BatchPartialUpdateResponseBuilder batchPartialUpdateResponseBuilder = new BatchPartialUpdateResponseBuilder(new ErrorResponseBuilder());
RestLiResponseData<BatchPartialUpdateResponseEnvelope> responseData = batchPartialUpdateResponseBuilder.buildRestLiResponseData(null, routingResult, result, headers, Collections.emptyList());
UpdateEntityStatus<TestRecord> updateEntityStatus = (UpdateEntityStatus<TestRecord>) responseData.getResponseEnvelope().getBatchResponseMap().get(id).getRecord();
Assert.assertNotNull(updateEntityStatus);
RecordTemplate returnedRecord = updateEntityStatus.getEntity();
Assert.assertEquals(returnedRecord.data().size(), 1, "Expected response record to be projected down to one field.");
Assert.assertEquals((int) returnedRecord.data().get("intField"), 2147, "Expected response record intField to match original.");
}
use of com.linkedin.restli.common.UpdateEntityStatus in project rest.li by linkedin.
the class LatencyInstrumentationResource method create.
/**
* This is the "upstream endpoint" which is queried directly by the integration test.
* This endpoint makes a call to {@link #batchPartialUpdate(BatchPatchRequest)} (the "downstream endpoint"),
* then packs all the client-side timing data into the original server-side request context.
*/
@ReturnEntity
@RestMethod.Create
public CreateKVResponse<Long, InstrumentationControl> create(InstrumentationControl control) {
final boolean forceException = control.isForceException();
final boolean useScatterGather = control.isUseScatterGather();
final String uriPrefix = control.getServiceUriPrefix();
// Build the downstream request
final BatchPartialUpdateEntityRequestBuilder<Long, InstrumentationControl> builder = new LatencyInstrumentationBuilders().batchPartialUpdateAndGet();
final PatchRequest<InstrumentationControl> patch = PatchGenerator.diffEmpty(control);
for (long i = 0; i < DOWNSTREAM_BATCH_SIZE; i++) {
builder.input(i, patch);
}
final BatchPartialUpdateEntityRequest<Long, InstrumentationControl> request = builder.build();
// Set up the Rest.li client config
final RestLiClientConfig clientConfig = new RestLiClientConfig();
clientConfig.setUseStreaming(control.isUseStreaming());
if (useScatterGather) {
clientConfig.setScatterGatherStrategy(new DefaultScatterGatherStrategy(new DummyUriMapper()));
}
final TransportClient transportClient = new HttpClientFactory.Builder().build().getClient(Collections.emptyMap());
final RestClient restClient = new ForceScatterGatherRestClient(new TransportClientAdapter(transportClient), uriPrefix, clientConfig);
final RequestContext serverRequestContext = getContext().getRawRequestContext();
final RequestContext clientRequestContext = new RequestContext();
// Load the timing importance threshold from the server context into the client context
clientRequestContext.putLocalAttr(TimingContextUtil.TIMING_IMPORTANCE_THRESHOLD_KEY_NAME, serverRequestContext.getLocalAttr(TimingContextUtil.TIMING_IMPORTANCE_THRESHOLD_KEY_NAME));
try {
// Make the request, then assert that the returned errors (if any) are as expected
BatchKVResponse<Long, UpdateEntityStatus<InstrumentationControl>> response = restClient.sendRequest(request, clientRequestContext).getResponseEntity();
final Map<Long, ErrorResponse> errors = response.getErrors();
if (forceException && errors.isEmpty()) {
throw new RestLiServiceException(HttpStatus.S_500_INTERNAL_SERVER_ERROR, "Expected failures for the downstream batch request, but found none.");
}
if (!forceException && !errors.isEmpty()) {
throw new RestLiServiceException(HttpStatus.S_500_INTERNAL_SERVER_ERROR, "Expected no failures for the downstream batch request, but found some.");
}
for (ErrorResponse errorResponse : errors.values()) {
if (!DOWNSTREAM_ERROR_CODE.equals(errorResponse.getCode())) {
throw new RestLiServiceException(HttpStatus.S_500_INTERNAL_SERVER_ERROR, "Encountered a downstream failure with an unexpected or missing error code.");
}
}
} catch (RemoteInvocationException e) {
throw new RestLiServiceException(HttpStatus.S_500_INTERNAL_SERVER_ERROR, "Downstream failures should be batch entry failures, but encountered a top-level request failure.", e);
}
Map<TimingKey, TimingContextUtil.TimingContext> clientTimingsMap = TimingContextUtil.getTimingsMap(clientRequestContext);
Map<TimingKey, TimingContextUtil.TimingContext> serverTimingsMap = TimingContextUtil.getTimingsMap(serverRequestContext);
// Load all client timings into the server timings map
serverTimingsMap.putAll(clientTimingsMap);
getContext().setResponseHeader(HAS_CLIENT_TIMINGS_HEADER, Boolean.TRUE.toString());
if (forceException) {
throw new RestLiServiceException(HttpStatus.S_400_BAD_REQUEST, "You wanted me to fail, so I failed.").setCode(UPSTREAM_ERROR_CODE);
}
return new CreateKVResponse<>(1L, control);
}
use of com.linkedin.restli.common.UpdateEntityStatus in project rest.li by linkedin.
the class BatchPartialUpdateResponseBuilder method buildUpdateStatus.
/**
* Defines how to build an update status for batch partial update. If the update response is an {@link UpdateEntityResponse}
* and the client is requesting the entities to be returned, then build an {@link UpdateEntityStatus} containing the
* entity to be returned for a given update response.
* @param resourceContext current resource context
* @param updateResponse update response returned by the resource method
* @return update status possibly containing the returned entity
*/
@Override
protected UpdateStatus buildUpdateStatus(ResourceContext resourceContext, UpdateResponse updateResponse) {
if (updateResponse instanceof UpdateEntityResponse && resourceContext.isReturnEntityRequested()) {
final RecordTemplate entity = ((UpdateEntityResponse<?>) updateResponse).getEntity();
final DataMap entityData = entity != null ? entity.data() : null;
final DataMap projectedData = RestUtils.projectFields(entityData, resourceContext);
return new UpdateEntityStatus<>(updateResponse.getStatus().getCode(), new AnyRecord(projectedData));
} else {
return super.buildUpdateStatus(resourceContext, updateResponse);
}
}
use of com.linkedin.restli.common.UpdateEntityStatus in project rest.li by linkedin.
the class TestParseqBasedFluentClientApiWithProjections method testBatchPartialUpdateAndGetWithProjection.
@Test
public void testBatchPartialUpdateAndGetWithProjection() throws Exception {
PartialUpdateGreeting greetings = new PartialUpdateGreetingFluentClient(_parSeqRestliClient, _parSeqUnitTestHelper.getEngine());
Map<Long, PatchRequest<Greeting>> inputs = new HashMap<>();
Greeting original = getGreeting();
String message = "Edited message: fluent api test partialUpdateAndGet";
Greeting update = getGreeting(message);
inputs.put(21L, PatchGenerator.diff(original, update));
inputs.put(22L, PatchGenerator.diff(original, update));
CompletionStage<Map<Long, UpdateEntityStatus<Greeting>>> result = greetings.batchPartialUpdateAndGet(inputs, optionalParams -> optionalParams.withMask(mask -> mask.withId().withMessage().withTone()));
CompletableFuture<Map<Long, UpdateEntityStatus<Greeting>>> future = result.toCompletableFuture();
Assert.assertNotNull(future.get(5000, TimeUnit.MILLISECONDS));
Assert.assertEquals(future.get().get(21L).getEntity().getId().longValue(), 21L);
Assert.assertEquals(future.get().get(21L).getEntity().getMessage(), message);
Assert.assertEquals(future.get().get(22L).getEntity().getId().longValue(), 22L);
Assert.assertEquals(future.get().get(22L).getEntity().getMessage(), message);
}
Aggregations