/** * Create a deadline that will expire at the specified offset from the current system clock. * @param duration A non-negative duration. * @param units The time unit for the duration. * @return A new deadline. */ public static Deadline after(long duration, TimeUnit units) { return after(duration, units, SYSTEM_TICKER); }
/** * Create a deadline that will expire at the specified offset from the current system clock. * @param duration A non-negative duration. * @param units The time unit for the duration. * @return A new deadline. */ public static Deadline after(long duration, TimeUnit units) { return after(duration, units, SYSTEM_TICKER); }
/** * Returns a new {@code CallOptions} with a deadline that is after the given {@code duration} from * now. */ public CallOptions withDeadlineAfter(long duration, TimeUnit unit) { return withDeadline(Deadline.after(duration, unit)); }
/** * Returns a new {@code CallOptions} with a deadline that is after the given {@code duration} from * now. */ public CallOptions withDeadlineAfter(long duration, TimeUnit unit) { return withDeadline(Deadline.after(duration, unit)); }
/** * Create a new context which will cancel itself after the given {@code duration} from now. * The returned context will cascade cancellation of its parent. Callers may explicitly cancel * the returned context prior to the deadline just as for {@link #withCancellation()}. If the unit * of work completes before the deadline, the context should be explicitly cancelled to allow * it to be garbage collected. * * <p>Sample usage: * <pre> * Context.CancellableContext withDeadline = Context.current() * .withDeadlineAfter(5, TimeUnit.SECONDS, scheduler); * try { * withDeadline.run(new Runnable() { * public void run() { * Context current = Context.current(); * while (!current.isCancelled()) { * keepWorking(); * } * } * }); * } finally { * withDeadline.cancel(null); * } * </pre> */ public CancellableContext withDeadlineAfter(long duration, TimeUnit unit, ScheduledExecutorService scheduler) { return withDeadline(Deadline.after(duration, unit), scheduler); }
/** * Create a new context which will cancel itself after the given {@code duration} from now. * The returned context will cascade cancellation of its parent. Callers may explicitly cancel * the returned context prior to the deadline just as for {@link #withCancellation()}. If the unit * of work completes before the deadline, the context should be explicitly cancelled to allow * it to be garbage collected. * * <p>Sample usage: * <pre> * Context.CancellableContext withDeadline = Context.current() * .withDeadlineAfter(5, TimeUnit.SECONDS, scheduler); * try { * withDeadline.run(new Runnable() { * public void run() { * Context current = Context.current(); * while (!current.isCancelled()) { * keepWorking(); * } * } * }); * } finally { * withDeadline.cancel(null); * } * </pre> */ public CancellableContext withDeadlineAfter(long duration, TimeUnit unit, ScheduledExecutorService scheduler) { return withDeadline(Deadline.after(duration, unit), scheduler); }
@Test public void testTimeoutToDeadlineConversion() { MethodDescriptor<Color, Money> descriptor = FakeServiceGrpc.METHOD_RECOGNIZE; @SuppressWarnings("unchecked") ClientCall<Color, Money> mockClientCall = Mockito.mock(ClientCall.class); @SuppressWarnings("unchecked") ClientCall.Listener<Money> mockListener = Mockito.mock(ClientCall.Listener.class); @SuppressWarnings("unchecked") Channel mockChannel = Mockito.mock(ManagedChannel.class); ArgumentCaptor<CallOptions> capturedCallOptions = ArgumentCaptor.forClass(CallOptions.class); Mockito.when(mockChannel.newCall(Mockito.eq(descriptor), capturedCallOptions.capture())) .thenReturn(mockClientCall); Duration timeout = Duration.ofSeconds(10); Deadline minExpectedDeadline = Deadline.after(timeout.getSeconds(), TimeUnit.SECONDS); GrpcCallContext context = GrpcCallContext.createDefault().withChannel(mockChannel).withTimeout(timeout); GrpcClientCalls.newCall(descriptor, context).start(mockListener, new Metadata()); Deadline maxExpectedDeadline = Deadline.after(timeout.getSeconds(), TimeUnit.SECONDS); Truth.assertThat(capturedCallOptions.getValue().getDeadline()).isAtLeast(minExpectedDeadline); Truth.assertThat(capturedCallOptions.getValue().getDeadline()).isAtMost(maxExpectedDeadline); }
@Test public void testTimeoutAfterDeadline() { MethodDescriptor<Color, Money> descriptor = FakeServiceGrpc.METHOD_RECOGNIZE; @SuppressWarnings("unchecked") ClientCall<Color, Money> mockClientCall = Mockito.mock(ClientCall.class); @SuppressWarnings("unchecked") ClientCall.Listener<Money> mockListener = Mockito.mock(ClientCall.Listener.class); @SuppressWarnings("unchecked") Channel mockChannel = Mockito.mock(ManagedChannel.class); ArgumentCaptor<CallOptions> capturedCallOptions = ArgumentCaptor.forClass(CallOptions.class); Mockito.when(mockChannel.newCall(Mockito.eq(descriptor), capturedCallOptions.capture())) .thenReturn(mockClientCall); // Configure a timeout that occurs after the grpc deadline Deadline priorDeadline = Deadline.after(5, TimeUnit.SECONDS); Duration timeout = Duration.ofSeconds(10); GrpcCallContext context = GrpcCallContext.createDefault() .withChannel(mockChannel) .withCallOptions(CallOptions.DEFAULT.withDeadline(priorDeadline)) .withTimeout(timeout); GrpcClientCalls.newCall(descriptor, context).start(mockListener, new Metadata()); // Verify that the timeout is ignored Truth.assertThat(capturedCallOptions.getValue().getDeadline()).isEqualTo(priorDeadline); }
Deadline.after(grpcContext.getTimeout().toMillis(), TimeUnit.MILLISECONDS); Deadline oldDeadline = callOptions.getDeadline();
Deadline.after(grpcContext.getTimeout().toMillis(), TimeUnit.MILLISECONDS); Deadline oldDeadline = callOptions.getDeadline();
@Override /** * Creates a {@link CallOptions} with a focus on {@link Deadlines}. Deadlines are decided in the following order: * <ol> * <li> If a user set a {@link Context} deadline (see {@link Context#getDeadline()}), use that</li> * <li> If a user configured deadlines via {@link CallOptionsConfig}, use it.</li> * <li> Otherwise, use {@link CallOptions#DEFAULT}.</li> * </ol> * */ public <RequestT> CallOptions create(MethodDescriptor<RequestT, ?> descriptor, RequestT request) { Deadline contextDeadline = Context.current().getDeadline(); if (contextDeadline != null) { return CallOptions.DEFAULT.withDeadline(contextDeadline); } else if (config.isUseTimeout() && request != null) { int timeout = isLongRequest(request) ? config.getLongRpcTimeoutMs() : config.getShortRpcTimeoutMs(); return CallOptions.DEFAULT.withDeadline(Deadline.after(timeout, TimeUnit.MILLISECONDS)); } else { return CallOptions.DEFAULT; } }
protected <ReqT,R> ListenableFuture<R> fuCall(MethodDescriptor<ReqT,R> method, ReqT request, CallOptions callOptions, long timeoutMs) { if(timeoutMs <= 0L) timeoutMs = defaultTimeoutMs; if(timeoutMs > 0L) { Deadline deadline = callOptions.getDeadline(); Deadline timeoutDeadline = Deadline.after(timeoutMs, MILLISECONDS); if(deadline == null || timeoutDeadline.isBefore(deadline)) { callOptions = callOptions.withDeadline(timeoutDeadline); } else if(deadline.isExpired()) { return Futures.immediateFailedFuture( Status.DEADLINE_EXCEEDED.asRuntimeException()); } } final CallOptions callOpts = callOptions; return sendViaEventLoop && !isEventThread.satisfied() ? Futures.submitAsync(() -> fuCall(method, request, callOpts), ses) : fuCall(method, request, callOpts); }
Deadline newDeadline = Deadline.after(info.timeoutNanos, TimeUnit.NANOSECONDS); Deadline existingDeadline = callOptions.getDeadline();