use of io.grpc.Deadline in project grpc-java by grpc.
the class StubConfigTest method testConfigureDeadline.
@Test
public void testConfigureDeadline() {
Deadline deadline = Deadline.after(2, NANOSECONDS);
// Create a default stub
TestServiceGrpc.TestServiceBlockingStub stub = TestServiceGrpc.newBlockingStub(channel);
assertNull(stub.getCallOptions().getDeadline());
// Reconfigure it
TestServiceGrpc.TestServiceBlockingStub reconfiguredStub = stub.withDeadline(deadline);
// New altered config
assertEquals(deadline, reconfiguredStub.getCallOptions().getDeadline());
// Default config unchanged
assertNull(stub.getCallOptions().getDeadline());
}
use of io.grpc.Deadline in project grpc-java by grpc.
the class CascadingTest method testDeadlinePropagation.
@Test
public void testDeadlinePropagation() throws Exception {
final AtomicInteger recursionDepthRemaining = new AtomicInteger(3);
final SettableFuture<Deadline> finalDeadline = SettableFuture.create();
class DeadlineSaver extends TestServiceGrpc.TestServiceImplBase {
@Override
public void unaryCall(final SimpleRequest request, final StreamObserver<SimpleResponse> responseObserver) {
Context.currentContextExecutor(otherWork).execute(new Runnable() {
@Override
public void run() {
try {
if (recursionDepthRemaining.decrementAndGet() == 0) {
finalDeadline.set(Context.current().getDeadline());
responseObserver.onNext(SimpleResponse.getDefaultInstance());
} else {
responseObserver.onNext(blockingStub.unaryCall(request));
}
responseObserver.onCompleted();
} catch (Exception ex) {
responseObserver.onError(ex);
}
}
});
}
}
server = InProcessServerBuilder.forName("channel").executor(otherWork).addService(new DeadlineSaver()).build().start();
Deadline initialDeadline = Deadline.after(1, TimeUnit.MINUTES);
blockingStub.withDeadline(initialDeadline).unaryCall(SimpleRequest.getDefaultInstance());
assertNotSame(initialDeadline, finalDeadline);
// Since deadline is re-calculated at each hop, some variance is acceptable and expected.
assertAbout(deadline()).that(finalDeadline.get()).isWithin(1, TimeUnit.SECONDS).of(initialDeadline);
}
use of io.grpc.Deadline in project grpc-java by grpc.
the class DeadlineSubject method isWithin.
/**
* Prepares for a check that the subject is deadline within the given tolerance of an
* expected value that will be provided in the next call in the fluent chain.
*/
@CheckReturnValue
public TolerantDeadlineComparison isWithin(final long delta, final TimeUnit timeUnit) {
return new TolerantDeadlineComparison() {
@Override
public void of(Deadline expected) {
Deadline actual = getSubject();
checkNotNull(actual, "actual value cannot be null. expected=%s", expected);
// This is probably overkill, but easier than thinking about overflow.
BigInteger actualTimeRemaining = BigInteger.valueOf(actual.timeRemaining(NANOSECONDS));
BigInteger expectedTimeRemaining = BigInteger.valueOf(expected.timeRemaining(NANOSECONDS));
BigInteger deltaNanos = BigInteger.valueOf(timeUnit.toNanos(delta));
if (actualTimeRemaining.subtract(expectedTimeRemaining).abs().compareTo(deltaNanos) > 0) {
failWithRawMessage("%s and <%s> should have been within <%sns> of each other", getDisplaySubject(), expected, deltaNanos);
}
}
};
}
use of io.grpc.Deadline in project grpc-java by grpc.
the class ClientCallImpl method start.
@Override
public void start(final Listener<RespT> observer, Metadata headers) {
checkState(stream == null, "Already started");
checkNotNull(observer, "observer");
checkNotNull(headers, "headers");
if (context.isCancelled()) {
// Context is already cancelled so no need to create a real stream, just notify the observer
// of cancellation via callback on the executor
stream = NoopClientStream.INSTANCE;
class ClosedByContext extends ContextRunnable {
ClosedByContext() {
super(context);
}
@Override
public void runInContext() {
closeObserver(observer, statusFromCancelled(context), new Metadata());
}
}
callExecutor.execute(new ClosedByContext());
return;
}
final String compressorName = callOptions.getCompressor();
Compressor compressor = null;
if (compressorName != null) {
compressor = compressorRegistry.lookupCompressor(compressorName);
if (compressor == null) {
stream = NoopClientStream.INSTANCE;
class ClosedByNotFoundCompressor extends ContextRunnable {
ClosedByNotFoundCompressor() {
super(context);
}
@Override
public void runInContext() {
closeObserver(observer, Status.INTERNAL.withDescription(String.format("Unable to find compressor by name %s", compressorName)), new Metadata());
}
}
callExecutor.execute(new ClosedByNotFoundCompressor());
return;
}
} else {
compressor = Codec.Identity.NONE;
}
prepareHeaders(headers, decompressorRegistry, compressor, statsTraceCtx);
Deadline effectiveDeadline = effectiveDeadline();
boolean deadlineExceeded = effectiveDeadline != null && effectiveDeadline.isExpired();
if (!deadlineExceeded) {
updateTimeoutHeaders(effectiveDeadline, callOptions.getDeadline(), context.getDeadline(), headers);
ClientTransport transport = clientTransportProvider.get(new PickSubchannelArgsImpl(method, headers, callOptions));
Context origContext = context.attach();
try {
stream = transport.newStream(method, headers, callOptions, statsTraceCtx);
} finally {
context.detach(origContext);
}
} else {
stream = new FailingClientStream(DEADLINE_EXCEEDED);
}
if (callOptions.getAuthority() != null) {
stream.setAuthority(callOptions.getAuthority());
}
if (callOptions.getMaxInboundMessageSize() != null) {
stream.setMaxInboundMessageSize(callOptions.getMaxInboundMessageSize());
}
if (callOptions.getMaxOutboundMessageSize() != null) {
stream.setMaxOutboundMessageSize(callOptions.getMaxOutboundMessageSize());
}
stream.setCompressor(compressor);
stream.start(new ClientStreamListenerImpl(observer));
// Delay any sources of cancellation after start(), because most of the transports are broken if
// they receive cancel before start. Issue #1343 has more details
// Propagate later Context cancellation to the remote side.
context.addListener(this, directExecutor());
if (effectiveDeadline != null && // If the context has the effective deadline, we don't need to schedule an extra task.
context.getDeadline() != effectiveDeadline) {
deadlineCancellationFuture = startDeadlineTimer(effectiveDeadline);
}
if (cancelListenersShouldBeRemoved) {
// Race detected! ClientStreamListener.closed may have been called before
// deadlineCancellationFuture was set / context listener added, thereby preventing the future
// and listener from being cancelled. Go ahead and cancel again, just to be sure it
// was cancelled.
removeContextListenerAndCancelDeadlineFuture();
}
}
Aggregations