use of io.grpc.ClientInterceptor in project grpc-java by grpc.
the class ManagedChannelImplTest method newCallWithConfigSelector.
@Test
public void newCallWithConfigSelector() {
FakeNameResolverFactory nameResolverFactory = new FakeNameResolverFactory.Builder(expectedUri).setServers(ImmutableList.of(addressGroup)).build();
channelBuilder.nameResolverFactory(nameResolverFactory);
channel = new ManagedChannelImpl(channelBuilder, mockTransportFactory, new FakeBackoffPolicyProvider(), balancerRpcExecutorPool, timer.getStopwatchSupplier(), Collections.<ClientInterceptor>emptyList(), timer.getTimeProvider());
nameResolverFactory.nextConfigOrError.set(ConfigOrError.fromConfig(ManagedChannelServiceConfig.empty()));
final Metadata.Key<String> metadataKey = Metadata.Key.of("test", Metadata.ASCII_STRING_MARSHALLER);
final CallOptions.Key<String> callOptionsKey = CallOptions.Key.create("test");
InternalConfigSelector configSelector = new InternalConfigSelector() {
@Override
public Result selectConfig(final PickSubchannelArgs args) {
return Result.newBuilder().setConfig(ManagedChannelServiceConfig.empty()).setInterceptor(// An interceptor that mutates CallOptions based on headers value.
new ClientInterceptor() {
String value = args.getHeaders().get(metadataKey);
@Override
public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(MethodDescriptor<ReqT, RespT> method, CallOptions callOptions, Channel next) {
callOptions = callOptions.withOption(callOptionsKey, value);
return next.newCall(method, callOptions);
}
}).build();
}
};
nameResolverFactory.nextAttributes.set(Attributes.newBuilder().set(InternalConfigSelector.KEY, configSelector).build());
channel.getState(true);
Metadata headers = new Metadata();
headers.put(metadataKey, "fooValue");
ClientStream mockStream = mock(ClientStream.class);
ClientCall<String, Integer> call = channel.newCall(method, CallOptions.DEFAULT);
call.start(mockCallListener, headers);
ArgumentCaptor<Helper> helperCaptor = ArgumentCaptor.forClass(null);
verify(mockLoadBalancerProvider).newLoadBalancer(helperCaptor.capture());
helper = helperCaptor.getValue();
// Make the transport available
Subchannel subchannel = createSubchannelSafely(helper, addressGroup, Attributes.EMPTY, subchannelStateListener);
requestConnectionSafely(helper, subchannel);
verify(mockTransportFactory).newClientTransport(any(SocketAddress.class), any(ClientTransportOptions.class), any(ChannelLogger.class));
MockClientTransportInfo transportInfo = transports.poll();
ConnectionClientTransport mockTransport = transportInfo.transport;
ManagedClientTransport.Listener transportListener = transportInfo.listener;
when(mockTransport.newStream(same(method), same(headers), any(CallOptions.class), ArgumentMatchers.<ClientStreamTracer[]>any())).thenReturn(mockStream);
transportListener.transportReady();
when(mockPicker.pickSubchannel(any(PickSubchannelArgs.class))).thenReturn(PickResult.withSubchannel(subchannel));
updateBalancingStateSafely(helper, READY, mockPicker);
executor.runDueTasks();
ArgumentCaptor<CallOptions> callOptionsCaptor = ArgumentCaptor.forClass(null);
verify(mockTransport).newStream(same(method), same(headers), callOptionsCaptor.capture(), ArgumentMatchers.<ClientStreamTracer[]>any());
assertThat(callOptionsCaptor.getValue().getOption(callOptionsKey)).isEqualTo("fooValue");
verify(mockStream).start(streamListenerCaptor.capture());
// Clean up as much as possible to allow the channel to terminate.
shutdownSafely(helper, subchannel);
timer.forwardNanos(TimeUnit.SECONDS.toNanos(ManagedChannelImpl.SUBCHANNEL_SHUTDOWN_DELAY_SECONDS));
}
use of io.grpc.ClientInterceptor in project grpc-java by grpc.
the class ManagedChannelImplTest method startCallBeforeNameResolution.
@Test
public void startCallBeforeNameResolution() throws Exception {
FakeNameResolverFactory nameResolverFactory = new FakeNameResolverFactory.Builder(expectedUri).setServers(ImmutableList.of(addressGroup)).build();
channelBuilder.nameResolverFactory(nameResolverFactory);
channel = new ManagedChannelImpl(channelBuilder, mockTransportFactory, new FakeBackoffPolicyProvider(), balancerRpcExecutorPool, timer.getStopwatchSupplier(), Collections.<ClientInterceptor>emptyList(), timer.getTimeProvider());
Map<String, Object> rawServiceConfig = parseConfig("{\"methodConfig\":[{" + "\"name\":[{\"service\":\"service\"}]," + "\"waitForReady\":true}]}");
ManagedChannelServiceConfig managedChannelServiceConfig = createManagedChannelServiceConfig(rawServiceConfig, null);
nameResolverFactory.nextConfigOrError.set(ConfigOrError.fromConfig(managedChannelServiceConfig));
Metadata headers = new Metadata();
ClientStream mockStream = mock(ClientStream.class);
ClientCall<String, Integer> call = channel.newCall(method, CallOptions.DEFAULT);
call.start(mockCallListener, headers);
ArgumentCaptor<Helper> helperCaptor = ArgumentCaptor.forClass(null);
verify(mockLoadBalancerProvider).newLoadBalancer(helperCaptor.capture());
helper = helperCaptor.getValue();
// Make the transport available
Subchannel subchannel = createSubchannelSafely(helper, addressGroup, Attributes.EMPTY, subchannelStateListener);
verify(mockTransportFactory, never()).newClientTransport(any(SocketAddress.class), any(ClientTransportOptions.class), any(ChannelLogger.class));
requestConnectionSafely(helper, subchannel);
verify(mockTransportFactory).newClientTransport(any(SocketAddress.class), any(ClientTransportOptions.class), any(ChannelLogger.class));
MockClientTransportInfo transportInfo = transports.poll();
ConnectionClientTransport mockTransport = transportInfo.transport;
ManagedClientTransport.Listener transportListener = transportInfo.listener;
when(mockTransport.newStream(same(method), same(headers), any(CallOptions.class), ArgumentMatchers.<ClientStreamTracer[]>any())).thenReturn(mockStream);
transportListener.transportReady();
when(mockPicker.pickSubchannel(any(PickSubchannelArgs.class))).thenReturn(PickResult.withSubchannel(subchannel));
updateBalancingStateSafely(helper, READY, mockPicker);
executor.runDueTasks();
ArgumentCaptor<CallOptions> callOptionsCaptor = ArgumentCaptor.forClass(null);
verify(mockTransport).newStream(same(method), same(headers), callOptionsCaptor.capture(), ArgumentMatchers.<ClientStreamTracer[]>any());
assertThat(callOptionsCaptor.getValue().isWaitForReady()).isTrue();
verify(mockStream).start(streamListenerCaptor.capture());
// Clean up as much as possible to allow the channel to terminate.
shutdownSafely(helper, subchannel);
timer.forwardNanos(TimeUnit.SECONDS.toNanos(ManagedChannelImpl.SUBCHANNEL_SHUTDOWN_DELAY_SECONDS));
}
use of io.grpc.ClientInterceptor in project grpc-java by grpc.
the class ManagedChannelImplTest method binaryLogInstalled.
@Test
public void binaryLogInstalled() throws Exception {
final SettableFuture<Boolean> intercepted = SettableFuture.create();
channelBuilder.binlog = new BinaryLog() {
@Override
public void close() throws IOException {
// noop
}
@Override
public <ReqT, RespT> ServerMethodDefinition<?, ?> wrapMethodDefinition(ServerMethodDefinition<ReqT, RespT> oMethodDef) {
return oMethodDef;
}
@Override
public Channel wrapChannel(Channel channel) {
return ClientInterceptors.intercept(channel, new ClientInterceptor() {
@Override
public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(MethodDescriptor<ReqT, RespT> method, CallOptions callOptions, Channel next) {
intercepted.set(true);
return next.newCall(method, callOptions);
}
});
}
};
createChannel();
ClientCall<String, Integer> call = channel.newCall(method, CallOptions.DEFAULT);
call.start(mockCallListener, new Metadata());
assertTrue(intercepted.get());
}
use of io.grpc.ClientInterceptor in project grpc-java by grpc.
the class FaultFilter method buildClientInterceptor.
@Nullable
@Override
public ClientInterceptor buildClientInterceptor(FilterConfig config, @Nullable FilterConfig overrideConfig, PickSubchannelArgs args, final ScheduledExecutorService scheduler) {
checkNotNull(config, "config");
if (overrideConfig != null) {
config = overrideConfig;
}
FaultConfig faultConfig = (FaultConfig) config;
Long delayNanos = null;
Status abortStatus = null;
if (faultConfig.maxActiveFaults() == null || activeFaultCounter.get() < faultConfig.maxActiveFaults()) {
Metadata headers = args.getHeaders();
if (faultConfig.faultDelay() != null) {
delayNanos = determineFaultDelayNanos(faultConfig.faultDelay(), headers);
}
if (faultConfig.faultAbort() != null) {
abortStatus = determineFaultAbortStatus(faultConfig.faultAbort(), headers);
}
}
if (delayNanos == null && abortStatus == null) {
return null;
}
final Long finalDelayNanos = delayNanos;
final Status finalAbortStatus = getAbortStatusWithDescription(abortStatus);
final class FaultInjectionInterceptor implements ClientInterceptor {
@Override
public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(final MethodDescriptor<ReqT, RespT> method, final CallOptions callOptions, final Channel next) {
Executor callExecutor = callOptions.getExecutor();
if (callExecutor == null) {
// This should never happen in practice because
// ManagedChannelImpl.ConfigSelectingClientCall always provides CallOptions with
// a callExecutor.
// TODO(https://github.com/grpc/grpc-java/issues/7868)
callExecutor = MoreExecutors.directExecutor();
}
if (finalDelayNanos != null) {
Supplier<? extends ClientCall<ReqT, RespT>> callSupplier;
if (finalAbortStatus != null) {
callSupplier = Suppliers.ofInstance(new FailingClientCall<ReqT, RespT>(finalAbortStatus, callExecutor));
} else {
callSupplier = new Supplier<ClientCall<ReqT, RespT>>() {
@Override
public ClientCall<ReqT, RespT> get() {
return next.newCall(method, callOptions);
}
};
}
final DelayInjectedCall<ReqT, RespT> delayInjectedCall = new DelayInjectedCall<>(finalDelayNanos, callExecutor, scheduler, callOptions.getDeadline(), callSupplier);
final class DeadlineInsightForwardingCall extends ForwardingClientCall<ReqT, RespT> {
@Override
protected ClientCall<ReqT, RespT> delegate() {
return delayInjectedCall;
}
@Override
public void start(Listener<RespT> listener, Metadata headers) {
Listener<RespT> finalListener = new SimpleForwardingClientCallListener<RespT>(listener) {
@Override
public void onClose(Status status, Metadata trailers) {
if (status.getCode().equals(Code.DEADLINE_EXCEEDED)) {
// TODO(zdapeng:) check effective deadline locally, and
// do the following only if the local deadline is exceeded.
// (If the server sends DEADLINE_EXCEEDED for its own deadline, then the
// injected delay does not contribute to the error, because the request is
// only sent out after the delay. There could be a race between local and
// remote, but it is rather rare.)
String description = String.format("Deadline exceeded after up to %d ns of fault-injected delay", finalDelayNanos);
if (status.getDescription() != null) {
description = description + ": " + status.getDescription();
}
status = Status.DEADLINE_EXCEEDED.withDescription(description).withCause(status.getCause());
// Replace trailers to prevent mixing sources of status and trailers.
trailers = new Metadata();
}
delegate().onClose(status, trailers);
}
};
delegate().start(finalListener, headers);
}
}
return new DeadlineInsightForwardingCall();
} else {
return new FailingClientCall<>(finalAbortStatus, callExecutor);
}
}
}
return new FaultInjectionInterceptor();
}
use of io.grpc.ClientInterceptor in project jetcd by coreos.
the class ClientConnectionManagerTest method testHeaders.
@Test
public void testHeaders() throws InterruptedException, ExecutionException {
final CountDownLatch latch = new CountDownLatch(1);
final ClientBuilder builder = TestUtil.client(cluster).header("MyHeader1", "MyHeaderVal1").header("MyHeader2", "MyHeaderVal2").interceptor(new ClientInterceptor() {
@Override
public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(MethodDescriptor<ReqT, RespT> method, CallOptions callOptions, Channel next) {
return new ForwardingClientCall.SimpleForwardingClientCall<ReqT, RespT>(next.newCall(method, callOptions)) {
@Override
public void start(Listener<RespT> responseListener, Metadata headers) {
super.start(responseListener, headers);
assertThat(headers.get(Metadata.Key.of("MyHeader1", Metadata.ASCII_STRING_MARSHALLER))).isEqualTo("MyHeaderVal1");
assertThat(headers.get(Metadata.Key.of("MyHeader2", Metadata.ASCII_STRING_MARSHALLER))).isEqualTo("MyHeaderVal2");
latch.countDown();
}
};
}
});
try (Client client = builder.build()) {
CompletableFuture<PutResponse> future = client.getKVClient().put(bytesOf("sample_key"), bytesOf("sample_key"));
latch.await(1, TimeUnit.MINUTES);
future.get();
}
}
Aggregations