use of io.grpc.Context in project grpc-java by grpc.
the class CascadingTest method testCascadingCancellationViaOuterContextCancellation.
/**
* Test {@link Context} cancellation propagates from the first node in the call chain all the way
* to the last.
*/
@Test
public void testCascadingCancellationViaOuterContextCancellation() throws Exception {
observedCancellations = new CountDownLatch(2);
receivedCancellations = new CountDownLatch(3);
Future<?> chainReady = startChainingServer(3);
CancellableContext context = Context.current().withCancellation();
Future<SimpleResponse> future;
Context prevContext = context.attach();
try {
future = futureStub.unaryCall(SimpleRequest.getDefaultInstance());
} finally {
context.detach(prevContext);
}
chainReady.get(5, TimeUnit.SECONDS);
context.cancel(null);
try {
future.get(5, TimeUnit.SECONDS);
fail("Expected cancellation");
} catch (ExecutionException ex) {
Status status = Status.fromThrowable(ex);
assertEquals(Status.Code.CANCELLED, status.getCode());
// Should have observed 2 cancellations responses from downstream servers
if (!observedCancellations.await(5, TimeUnit.SECONDS)) {
fail("Expected number of cancellations not observed by clients");
}
if (!receivedCancellations.await(5, TimeUnit.SECONDS)) {
fail("Expected number of cancellations to be received by servers not observed");
}
}
}
use of io.grpc.Context in project google-cloud-java by GoogleCloudPlatform.
the class ITWriteTest method deadline.
@Test
public void deadline() {
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
// Cloud Spanner is fast, but not this fast :-)
Context.CancellableContext context = Context.current().withDeadlineAfter(10, TimeUnit.NANOSECONDS, executor);
Runnable work = context.wrap(new Runnable() {
@Override
public void run() {
write(baseInsert().set("BoolValue").to(true).build());
}
});
try {
work.run();
} catch (SpannerException e) {
MatcherAssert.assertThat(e, isSpannerException(ErrorCode.DEADLINE_EXCEEDED));
} finally {
executor.shutdown();
}
}
use of io.grpc.Context in project google-cloud-java by GoogleCloudPlatform.
the class SpannerImpl method runWithRetries.
/**
* Helper to execute some work, retrying with backoff on retryable errors.
*
* <p>TODO: Consider replacing with RetryHelper from gcloud-core.
*/
static <T> T runWithRetries(Callable<T> callable) {
// Use same backoff setting as abort, somewhat arbitrarily.
ExponentialBackOff backOff = newBackOff();
Context context = Context.current();
while (true) {
try {
return callable.call();
} catch (SpannerException e) {
if (!e.isRetryable()) {
throw e;
}
logger.log(Level.FINE, "Retryable exception, will sleep and retry", e);
backoffSleep(context, backOff);
} catch (Exception e) {
throw Throwables.propagate(e);
}
}
}
use of io.grpc.Context in project google-cloud-java by GoogleCloudPlatform.
the class SpannerImpl method backoffSleep.
private static void backoffSleep(Context context, long backoffMillis) throws SpannerException {
final CountDownLatch latch = new CountDownLatch(1);
final Context.CancellationListener listener = new Context.CancellationListener() {
@Override
public void cancelled(Context context) {
// Wakeup on cancellation / DEADLINE_EXCEEDED.
latch.countDown();
}
};
context.addListener(listener, DirectExecutor.INSTANCE);
try {
if (backoffMillis == BackOff.STOP) {
// Highly unlikely but we handle it just in case.
backoffMillis = MAX_BACKOFF_MS;
}
if (latch.await(backoffMillis, TimeUnit.MILLISECONDS)) {
// Woken by context cancellation.
throw newSpannerExceptionForCancellation(context, null);
}
} catch (InterruptedException interruptExcept) {
throw newSpannerExceptionForCancellation(context, interruptExcept);
} finally {
context.removeListener(listener);
}
}
use of io.grpc.Context in project google-cloud-java by GoogleCloudPlatform.
the class SpannerImplRetryTest method contextDeadlineExceeded.
@Test
public void contextDeadlineExceeded() {
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
Context.CancellableContext context = Context.current().withDeadlineAfter(10, TimeUnit.NANOSECONDS, executor);
Mockito.when(callable.call()).thenThrow(new RetryableException(ErrorCode.UNAVAILABLE, "Failure #1"));
Runnable work = context.wrap(new Runnable() {
@Override
public void run() {
SpannerImpl.runWithRetries(callable);
}
});
expectedException.expect(isSpannerException(ErrorCode.DEADLINE_EXCEEDED));
work.run();
}
Aggregations