use of io.mantisrx.runtime.source.http.HttpClientFactory in project mantis by Netflix.
the class HttpSourceImplTest method testTimeoutShouldUnsubscribeServer.
@Test
public void testTimeoutShouldUnsubscribeServer() throws Exception {
HttpClientFactory<ByteBuf, ByteBuf> factory = new HttpClientFactory<ByteBuf, ByteBuf>() {
@Override
public HttpClient<ByteBuf, ByteBuf> createClient(ServerInfo server) {
ClientConfig clientConfig = new ClientConfig.Builder().readTimeout(10, TimeUnit.MILLISECONDS).build();
return new HttpClientBuilder<ByteBuf, ByteBuf>(server.getHost(), server.getPort()).config(clientConfig).build();
}
};
HttpSourceImpl<ByteBuf, ByteBuf, ServerContext<ByteBuf>> source = HttpSourceImpl.builder(factory, HttpRequestFactories.createGetFactory("test/timeout?timeout=10000"), HttpSourceImpl.<ByteBuf>contextWrapper()).withActivityObserver(sourceObserver).resumeWith(new ClientResumePolicy<ByteBuf, ByteBuf>() {
@Override
public Observable<HttpClientResponse<ByteBuf>> onError(ServerClientContext<ByteBuf, ByteBuf> clientContext, int attempts, Throwable error) {
// TODO Auto-generated method stub
return null;
}
@Override
public Observable<HttpClientResponse<ByteBuf>> onCompleted(ServerClientContext<ByteBuf, ByteBuf> clientContext, int attempts) {
// TODO Auto-generated method stub
return null;
}
}).withServerProvider(new HttpServerProvider() {
@Override
public Observable<ServerInfo> getServersToAdd() {
return Observable.from(localServerProvider.getServers()).map(new Func1<Server, ServerInfo>() {
@Override
public ServerInfo call(Server server) {
return toServerInfo(server);
}
});
}
@Override
public Observable<ServerInfo> getServersToRemove() {
return Observable.empty();
}
}).build();
final CountDownLatch latch = new CountDownLatch(1);
final AtomicReference<Throwable> ex = new AtomicReference<>();
final AtomicReference<ServerContext<ByteBuf>> items = new AtomicReference<>();
Observable.merge(source.call(new Context(), new Index(1, 1))).subscribe(new Subscriber<ServerContext<ByteBuf>>() {
@Override
public void onCompleted() {
latch.countDown();
}
@Override
public void onError(Throwable e) {
ex.set(e);
latch.countDown();
}
@Override
public void onNext(ServerContext<ByteBuf> pair) {
items.set(pair);
}
});
if (!latch.await(5, TimeUnit.SECONDS)) {
fail("The test case should finish way sooner than 5 seconds. ");
}
Assert.assertNull("The timeout error should be captured by the client so it does not surface to the source", ex.get());
Assert.assertNull("There should be no emitted item due to connection timeout", items.get());
for (Server server : localServerProvider.getServers()) {
ServerInfo serverInfo = toServerInfo(server);
assertEquals("There should be no source level error", 0, sourceObserver.getErrorCount());
assertEquals("There should be one connection attempt per server", 1, sourceObserver.getCount(serverInfo, EventType.CONNECTION_ATTEMPTED));
assertEquals("There should be no established connection per server due to read timeout. ", 0, sourceObserver.getCount(serverInfo, EventType.CONNECTION_ESTABLISHED));
assertEquals("There should no subscribed server because of read timeout", 0, sourceObserver.getCount(serverInfo, EventType.SUBSCRIPTION_ESTABLISHED));
}
}
use of io.mantisrx.runtime.source.http.HttpClientFactory in project mantis by Netflix.
the class HttpSourceImplTest method testConnectionFailureShouldBeCaptured.
@Test
public void testConnectionFailureShouldBeCaptured() throws Exception {
HttpClientFactory<ByteBuf, ByteBuf> factory = new HttpClientFactory<ByteBuf, ByteBuf>() {
@Override
public HttpClient<ByteBuf, ByteBuf> createClient(ServerInfo server) {
HttpClientBuilder<ByteBuf, ByteBuf> clientBuilder = new HttpClientBuilder<>(server.getHost(), server.getPort());
return clientBuilder.channelOption(ChannelOption.CONNECT_TIMEOUT_MILLIS, 100).build();
}
};
HttpSourceImpl<ByteBuf, ByteBuf, ServerContext<ByteBuf>> source = HttpSourceImpl.builder(factory, HttpRequestFactories.createGetFactory("/"), HttpSourceImpl.<ByteBuf>contextWrapper()).withActivityObserver(sourceObserver).withServerProvider(new HttpServerProvider() {
@Override
public Observable<ServerInfo> getServersToAdd() {
return Observable.just(new ServerInfo("localhost", UNUSED_PORT));
}
@Override
public Observable<ServerInfo> getServersToRemove() {
return Observable.empty();
}
}).build();
final CountDownLatch latch = new CountDownLatch(1);
final AtomicReference<Throwable> ex = new AtomicReference<>();
final AtomicReference<ServerContext<ByteBuf>> items = new AtomicReference<>();
Observable.merge(source.call(new Context(), new Index(1, 1))).subscribe(new Subscriber<ServerContext<ByteBuf>>() {
@Override
public void onCompleted() {
latch.countDown();
}
@Override
public void onError(Throwable e) {
ex.set(e);
latch.countDown();
}
@Override
public void onNext(ServerContext<ByteBuf> pair) {
items.set(pair);
}
});
if (!latch.await(5, TimeUnit.HOURS)) {
fail("The test case should finish way sooner than 5 seconds. ");
}
Assert.assertNull("The connection error should be captured per server, therefore not propagated up to the entire source.", ex.get());
Assert.assertNull("There should be no emitted item due to connection timeout", items.get());
}
use of io.mantisrx.runtime.source.http.HttpClientFactory in project mantis by Netflix.
the class HttpSourceImplTest method testResumeOnTimeout.
@Test
public void testResumeOnTimeout() throws Exception {
HttpClientFactory<ByteBuf, ByteBuf> factory = new HttpClientFactory<ByteBuf, ByteBuf>() {
@Override
public HttpClient<ByteBuf, ByteBuf> createClient(ServerInfo server) {
ClientConfig clientConfig = new ClientConfig.Builder().readTimeout(10, TimeUnit.MILLISECONDS).build();
return new HttpClientBuilder<ByteBuf, ByteBuf>(server.getHost(), server.getPort()).config(clientConfig).build();
}
};
final ConcurrentMap<ServerInfo, AtomicInteger> resumptions = new ConcurrentHashMap<>();
for (ServerInfo server : localServerProvider.getServerInfos()) {
resumptions.put(server, new AtomicInteger());
}
final int maxRepeat = 5;
HttpSourceImpl<ByteBuf, ByteBuf, ServerContext<ByteBuf>> source = HttpSourceImpl.builder(factory, HttpRequestFactories.createGetFactory("test/timeout?timeout=10000"), HttpSourceImpl.<ByteBuf>contextWrapper()).withActivityObserver(sourceObserver).resumeWith(new ClientResumePolicy<ByteBuf, ByteBuf>() {
@Override
public Observable<HttpClientResponse<ByteBuf>> onError(ServerClientContext<ByteBuf, ByteBuf> clientContext, int attempts, Throwable error) {
if (attempts <= maxRepeat) {
resumptions.get(clientContext.getServer()).incrementAndGet();
return clientContext.newResponse();
}
return null;
}
@Override
public Observable<HttpClientResponse<ByteBuf>> onCompleted(ServerClientContext<ByteBuf, ByteBuf> clientContext, int attempts) {
return null;
}
}).withServerProvider(localServerProvider).build();
final CountDownLatch latch = new CountDownLatch(1);
final AtomicReference<Throwable> ex = new AtomicReference<>();
final AtomicReference<ServerContext<ByteBuf>> items = new AtomicReference<>();
Observable.merge(source.call(new Context(), new Index(1, 1))).subscribe(new Subscriber<ServerContext<ByteBuf>>() {
@Override
public void onCompleted() {
latch.countDown();
}
@Override
public void onError(Throwable e) {
ex.set(e);
latch.countDown();
}
@Override
public void onNext(ServerContext<ByteBuf> pair) {
items.set(pair);
}
});
if (!latch.await(10, TimeUnit.SECONDS)) {
fail("The test case should finish way sooner than 10 seconds. ");
}
Assert.assertNull("The timeout error should be captured by the client so it does not surface to the source", ex.get());
Assert.assertNull("There should be no emitted item due to connection timeout", items.get());
for (ServerInfo serverInfo : localServerProvider.getServerInfos()) {
assertEquals("There should be no source level error", 0, sourceObserver.getErrorCount());
assertEquals("There should be one connection attempt per server per retry", maxRepeat + 1, sourceObserver.getCount(serverInfo, EventType.CONNECTION_ATTEMPTED));
assertEquals("There should be no established connection per server due to read timeout. ", 0, sourceObserver.getCount(serverInfo, EventType.CONNECTION_ESTABLISHED));
assertEquals("There should no subscribed server because of read timeout", 0, sourceObserver.getCount(serverInfo, EventType.SUBSCRIPTION_ESTABLISHED));
assertEquals("Each server will repeat exactly " + maxRepeat + " times", maxRepeat, resumptions.get(serverInfo).get());
}
}
Aggregations