/** * Returns the {@link Executor} that is handling the current {@link Request}. */ default Executor executor() { // The implementation is the same as eventLoop but we expose as an Executor as well given // how much easier it is to write tests for an Executor (i.e., // when(ctx.executor()).thenReturn(MoreExecutors.directExecutor())); return eventLoop(); }
/** * Returns an {@link EventLoop} that will make sure this {@link RequestContext} is set as the current * context before executing any callback. */ default EventLoop contextAwareEventLoop() { return new RequestContextAwareEventLoop(this, eventLoop()); }
@Override public EventLoop eventLoop() { return delegate().eventLoop(); }
@Override @Nullable public TraceContext get() { final RequestContext ctx = getRequestContextOrWarnOnce(); if (ctx == null) { return null; } if (ctx.eventLoop().inEventLoop()) { return ctx.attr(TRACE_CONTEXT_KEY).get(); } else { final TraceContext threadLocalContext = THREAD_LOCAL_CONTEXT.get(); if (threadLocalContext != null) { return threadLocalContext; } // First span on a non-request thread will use the request's TraceContext as a parent. return ctx.attr(TRACE_CONTEXT_KEY).get(); } }
@Before public void setup() { when(mockRequestContext.eventLoop()).thenReturn(eventLoop); when(mockRequestContext2.eventLoop()).thenReturn(eventLoop); when(eventLoop.inEventLoop()).thenReturn(true); when(mockRequestContext.attr(isA(AttributeKey.class))).thenAnswer( (Answer<Attribute>) invocation -> attrs1.attr(invocation.getArgument(0))); when(mockRequestContext2.attr(isA(AttributeKey.class))).thenAnswer( (Answer<Attribute>) invocation -> attrs2.attr(invocation.getArgument(0))); }
@Override public Scope newScope(@Nullable TraceContext currentSpan) { // Handle inspection added to ensure we can fail-fast if this isn't installed. if (currentSpan != null && PingPongExtra.maybeSetPong(currentSpan)) { return Scope.NOOP; } final RequestContext ctx = getRequestContextOrWarnOnce(); if (ctx == null) { return INCOMPLETE_CONFIGURATION_SCOPE; } if (ctx.eventLoop().inEventLoop()) { return createScopeForRequestThread(ctx, currentSpan); } else { // The RequestContext is the canonical thread-local storage for the thread processing the request. // However, when creating spans on other threads (e.g., a thread-pool), we must use separate // thread-local storage to prevent threads from replacing the same trace context. return createScopeForNonRequestThread(currentSpan); } }
@Override protected void configure(ServerBuilder sb) throws Exception { sb.gracefulShutdownTimeout(1000L, 2000L); sb.defaultRequestTimeoutMillis(0); // Disable RequestTimeoutException. sb.service("/sleep", THttpService.of( (AsyncIface) (milliseconds, resultHandler) -> RequestContext.current().eventLoop().schedule( () -> resultHandler.onComplete(milliseconds), milliseconds, MILLISECONDS))); } };
private <T> void scheduleTimeout(CompletableFuture<T> result, long timeoutMillis) { pendingFutures.add(result); final ScheduledFuture<?> timeoutFuture; if (timeoutMillis > 0) { timeoutMillis = applyJitter(timeoutMillis); final EventLoop eventLoop = RequestContext.current().eventLoop(); timeoutFuture = eventLoop.schedule(() -> result.completeExceptionally(CANCELLATION_EXCEPTION), timeoutMillis, TimeUnit.MILLISECONDS); } else { timeoutFuture = null; } result.whenComplete((revision, cause) -> { if (timeoutFuture != null) { timeoutFuture.cancel(true); } pendingFutures.remove(result); }); }
private <T> void scheduleTimeout(CompletableFuture<T> result, long timeoutMillis) { pendingFutures.add(result); final ScheduledFuture<?> timeoutFuture; if (timeoutMillis > 0) { timeoutMillis = WatchTimeout.makeReasonable(timeoutMillis); timeoutMillis = applyJitter(timeoutMillis); final EventLoop eventLoop = RequestContext.current().eventLoop(); timeoutFuture = eventLoop.schedule(() -> result.completeExceptionally(CANCELLATION_EXCEPTION), timeoutMillis, TimeUnit.MILLISECONDS); } else { timeoutFuture = null; } result.whenComplete((revision, cause) -> { if (timeoutFuture != null) { timeoutFuture.cancel(true); } pendingFutures.remove(result); }); }
private <T> void scheduleTimeout(CompletableFuture<T> result, long timeoutMillis) { pendingFutures.add(result); final ScheduledFuture<?> timeoutFuture; if (timeoutMillis > 0) { timeoutMillis = WatchTimeout.makeReasonable(timeoutMillis); timeoutMillis = applyJitter(timeoutMillis); final EventLoop eventLoop = RequestContext.current().eventLoop(); timeoutFuture = eventLoop.schedule(() -> result.completeExceptionally(CANCELLATION_EXCEPTION), timeoutMillis, TimeUnit.MILLISECONDS); } else { timeoutFuture = null; } result.whenComplete((revision, cause) -> { if (timeoutFuture != null) { timeoutFuture.cancel(true); } pendingFutures.remove(result); }); }