Search in sources :

Example 16 with Index

use of io.mantisrx.runtime.source.Index in project mantis by Netflix.

the class HttpSourceImplTest method testGettingStreamFromMultipleServers.

@Test
public void testGettingStreamFromMultipleServers() throws Exception {
    HttpSourceImpl<ByteBuf, ServerSentEvent, ServerContext<ServerSentEvent>> source = createStreamingSource();
    final AtomicInteger counter = new AtomicInteger();
    final CountDownLatch done = new CountDownLatch(1);
    final ConcurrentHashMap<String, AtomicInteger> result = new ConcurrentHashMap<>();
    Observable.merge(source.call(new Context(), new Index(1, 1))).doOnNext(new Action1<ServerContext<ServerSentEvent>>() {

        @Override
        public void call(ServerContext<ServerSentEvent> pair) {
            assertTrue(pair.getValue().contentAsString().contains("line"));
            counter.incrementAndGet();
            String msg = pair.getValue().contentAsString();
            result.putIfAbsent(msg, new AtomicInteger());
            result.get(msg).incrementAndGet();
        }
    }).doOnError(new Action1<Throwable>() {

        @Override
        public void call(Throwable throwable) {
            fail("Unexpected failure: " + throwable);
        }
    }).doAfterTerminate(new Action0() {

        @Override
        public void call() {
            done.countDown();
        }
    }).subscribe();
    long waitSeconds = 3;
    boolean timedout = !done.await(waitSeconds, TimeUnit.SECONDS);
    if (timedout) {
        fail(String.format("Waited at least %d seconds for the test to finish. Something is wrong", waitSeconds));
    }
    assertEquals(String.format("%d servers => the result has %d times of a single stream", localServerProvider.serverSize(), localServerProvider.serverSize()), counter.get(), RequestProcessor.smallStreamContent.size() * localServerProvider.serverSize());
    for (String data : RequestProcessor.smallStreamContent) {
        assertEquals(String.format("%d servers => %d identical copies per message", localServerProvider.serverSize(), localServerProvider.serverSize()), localServerProvider.serverSize(), result.get(data).get());
    }
    for (Server server : localServerProvider.getServers()) {
        assertEquals("There should be one completion per server", 1, sourceObserver.getCount(toServerInfo(server), EventType.SOURCE_COMPLETED));
        assertEquals("There should be one un-subscription per server", 1, sourceObserver.getCount(toServerInfo(server), EventType.CONNECTION_UNSUBSCRIBED));
        assertEquals("There should be no error", 0, sourceObserver.getCount(toServerInfo(server), EventType.SUBSCRIPTION_FAILED));
        assertEquals("There should be one connection per server", 1, sourceObserver.getCount(toServerInfo(server), EventType.CONNECTION_ESTABLISHED));
    }
    assertEquals(1, sourceObserver.getCompletionCount());
    assertEquals(0, sourceObserver.getErrorCount());
    Set<EventType> events = sourceObserver.getEvents();
    assertEquals(EXPECTED_EVENTS_SETS, events);
    for (EventType event : events) {
        assertEquals("Each event should be recorded exactly once per server", localServerProvider.serverSize(), sourceObserver.getEventCount(event));
    }
    assertEquals("completed source should clean up its retry servers", 0, source.getRetryServers().size());
}
Also used : Context(io.mantisrx.runtime.Context) Action0(rx.functions.Action0) Action1(rx.functions.Action1) Server(io.mantisrx.runtime.source.http.LocalServerProvider.Server) EventType(io.mantisrx.runtime.source.http.impl.HttpSourceImpl.HttpSourceEvent.EventType) ServerSentEvent(mantis.io.reactivex.netty.protocol.http.sse.ServerSentEvent) Index(io.mantisrx.runtime.source.Index) ByteBuf(io.netty.buffer.ByteBuf) CountDownLatch(java.util.concurrent.CountDownLatch) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) Test(org.junit.Test)

Example 17 with Index

use of io.mantisrx.runtime.source.Index in project mantis by Netflix.

the class HttpSourceImplTest method testStreamingErrorFromServerWillNotCompleteSource.

@Test
public void testStreamingErrorFromServerWillNotCompleteSource() throws Exception {
    int eventCount = 20;
    HttpSourceImpl<ByteBuf, ServerSentEvent, ServerContext<ServerSentEvent>> source = createStreamingSource("test/finiteStream?count=" + eventCount);
    final CountDownLatch latch = new CountDownLatch(1);
    final AtomicReference<Throwable> ex = new AtomicReference<>();
    final ConcurrentHashMap<ServerInfo, Set<String>> items = new ConcurrentHashMap<>();
    Observable.merge(source.call(new Context(), new Index(1, 1))).subscribe(new Subscriber<ServerContext<ServerSentEvent>>() {

        @Override
        public void onCompleted() {
            latch.countDown();
        }

        @Override
        public void onError(Throwable e) {
            ex.set(e);
            latch.countDown();
        }

        @Override
        public void onNext(ServerContext<ServerSentEvent> pair) {
            items.putIfAbsent(pair.getServer(), new HashSet<String>());
            items.get(pair.getServer()).add(pair.getValue().contentAsString());
        }
    });
    if (latch.await(5, TimeUnit.SECONDS)) {
        fail("The test case should not finish at all");
    }
    Assert.assertNull("The timeout error should be captured by the client so it does not surface to the source", ex.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 one established connection per server ", 1, sourceObserver.getCount(serverInfo, EventType.CONNECTION_ESTABLISHED));
        assertEquals("There should no subscribed server because of read timeout", 1, sourceObserver.getCount(serverInfo, EventType.SUBSCRIPTION_ESTABLISHED));
        assertEquals(String.format("There should be %d item before simulated error per server", eventCount), eventCount, items.get(serverInfo).size());
    }
}
Also used : Context(io.mantisrx.runtime.Context) Set(java.util.Set) HashSet(java.util.HashSet) Server(io.mantisrx.runtime.source.http.LocalServerProvider.Server) ServerInfo(mantis.io.reactivex.netty.client.RxClient.ServerInfo) ServerSentEvent(mantis.io.reactivex.netty.protocol.http.sse.ServerSentEvent) AtomicReference(java.util.concurrent.atomic.AtomicReference) Index(io.mantisrx.runtime.source.Index) ByteBuf(io.netty.buffer.ByteBuf) CountDownLatch(java.util.concurrent.CountDownLatch) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashSet(java.util.HashSet) Test(org.junit.Test)

Example 18 with Index

use of io.mantisrx.runtime.source.Index in project mantis by Netflix.

the class HttpSourceImplTest method testGettingSingleEntityFromMultipleServers.

@Test
public void testGettingSingleEntityFromMultipleServers() throws Exception {
    HttpSourceImpl<ByteBuf, ByteBuf, ServerContext<ByteBuf>> source = createSingleEntitySource();
    final AtomicInteger counter = new AtomicInteger();
    final CountDownLatch done = new CountDownLatch(1);
    Observable.merge(source.call(new Context(), new Index(1, 1))).map(new Func1<ServerContext<ByteBuf>, ServerContext<String>>() {

        @Override
        public ServerContext<String> call(ServerContext<ByteBuf> pair) {
            return new ServerContext<>(pair.getServer(), pair.getValue().toString(Charset.defaultCharset()));
        }
    }).doOnNext(new Action1<ServerContext<String>>() {

        @Override
        public void call(ServerContext<String> pair) {
            counter.incrementAndGet();
            assertEquals(RequestProcessor.SINGLE_ENTITY_RESPONSE, pair.getValue());
        }
    }).doOnError(new Action1<Throwable>() {

        @Override
        public void call(Throwable throwable) {
            fail("Unexpected failure: " + throwable);
        }
    }).doAfterTerminate(new Action0() {

        @Override
        public void call() {
            done.countDown();
        }
    }).subscribe();
    done.await(3000, TimeUnit.SECONDS);
    assertEquals(String.format("There should be exactly one response from each of the %d servers", localServerProvider.serverSize()), localServerProvider.serverSize(), counter.get());
    for (Server server : localServerProvider.getServers()) {
        ServerInfo serverInfo = toServerInfo(server);
        assertEquals("There should be one completion per server", 1, sourceObserver.getCount(serverInfo, EventType.SOURCE_COMPLETED));
        assertEquals("There should be one un-subscription per server", 1, sourceObserver.getCount(serverInfo, EventType.CONNECTION_UNSUBSCRIBED));
        assertEquals("There should be no error", 0, sourceObserver.getCount(serverInfo, EventType.SUBSCRIPTION_FAILED));
        assertEquals("There should be one connection per server", 1, sourceObserver.getCount(serverInfo, EventType.SUBSCRIPTION_ESTABLISHED));
    }
    assertEquals(1, sourceObserver.getCompletionCount());
    assertEquals(0, sourceObserver.getErrorCount());
    Set<EventType> events = sourceObserver.getEvents();
    assertEquals(EXPECTED_EVENTS_SETS, events);
    for (EventType event : events) {
        assertEquals("Each event should be recorded exactly once per server", localServerProvider.serverSize(), sourceObserver.getEventCount(event));
    }
}
Also used : Context(io.mantisrx.runtime.Context) Action0(rx.functions.Action0) Action1(rx.functions.Action1) Server(io.mantisrx.runtime.source.http.LocalServerProvider.Server) EventType(io.mantisrx.runtime.source.http.impl.HttpSourceImpl.HttpSourceEvent.EventType) ServerInfo(mantis.io.reactivex.netty.client.RxClient.ServerInfo) Index(io.mantisrx.runtime.source.Index) ByteBuf(io.netty.buffer.ByteBuf) CountDownLatch(java.util.concurrent.CountDownLatch) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Test(org.junit.Test)

Example 19 with Index

use of io.mantisrx.runtime.source.Index in project mantis by Netflix.

the class HttpSourceImplTest method testRemovedServerWillBeUnsubscribed.

@Test
public void testRemovedServerWillBeUnsubscribed() throws Exception {
    HttpSourceImpl<ByteBuf, ServerSentEvent, ServerContext<ServerSentEvent>> source = createStreamingSource("test/infStream");
    final AtomicInteger counter = new AtomicInteger();
    final CountDownLatch done = new CountDownLatch(1);
    final ConcurrentHashMap<String, AtomicInteger> result = new ConcurrentHashMap<>();
    final ConcurrentMap<ServerInfo, CountDownLatch> serverRemovalLatch = new ConcurrentHashMap<>();
    for (Server server : localServerProvider.getServers()) {
        serverRemovalLatch.put(toServerInfo(server), new CountDownLatch(1));
    }
    Observable.merge(source.call(new Context(), new Index(1, 1))).doOnNext(new Action1<ServerContext<ServerSentEvent>>() {

        @Override
        public void call(ServerContext<ServerSentEvent> pair) {
            try {
                assertTrue(pair.getValue().contentAsString().contains("line"));
                counter.incrementAndGet();
                String msg = pair.getValue().contentAsString();
                result.putIfAbsent(msg, new AtomicInteger());
                result.get(msg).incrementAndGet();
            } finally {
                serverRemovalLatch.get(pair.getServer()).countDown();
            }
        }
    }).doOnError(new Action1<Throwable>() {

        @Override
        public void call(Throwable throwable) {
            fail("Unexpected failure: " + throwable);
        }
    }).doAfterTerminate(new Action0() {

        @Override
        public void call() {
            done.countDown();
        }
    }).subscribe();
    for (Server server : localServerProvider.getServers()) {
        serverRemovalLatch.get(toServerInfo(server)).await();
        localServerProvider.removeServer(toServerInfo(server));
    }
    long waitSeconds = 5;
    boolean timedout = !done.await(waitSeconds, TimeUnit.SECONDS);
    if (timedout) {
        fail(String.format("Waited at least %d seconds for the test to finish. Connection to at least one server is not unsubscribed.", waitSeconds));
    }
    assertTrue(String.format("Each server should emit at least one event before being canceled. Expected counter >= %d, actual counter: %d", localServerProvider.serverSize(), counter.get()), counter.get() >= localServerProvider.serverSize());
    for (Server server : localServerProvider.getServers()) {
        ServerInfo serverInfo = toServerInfo(server);
        assertEquals("There should be one completion per server", 1, sourceObserver.getCount(serverInfo, EventType.SOURCE_COMPLETED));
        assertEquals("There should be one un-subscription per server", 1, sourceObserver.getCount(serverInfo, EventType.CONNECTION_UNSUBSCRIBED));
        assertEquals("There should be no error", 0, sourceObserver.getCount(serverInfo, EventType.SUBSCRIPTION_FAILED));
        assertEquals("There should be one connection per server", 1, sourceObserver.getCount(serverInfo, EventType.SUBSCRIPTION_ESTABLISHED));
        assertEquals(String.format("There should be exactly one cancellation event per server for %d servers. ", localServerProvider.serverSize()), 1, sourceObserver.getCount(serverInfo, EventType.SUBSCRIPTION_CANCELED));
    }
    assertEquals("The source should emit exactly one completion event", 1, sourceObserver.getCompletionCount());
    assertEquals("The server should not have any error event", 0, sourceObserver.getErrorCount());
    Set<EventType> events = sourceObserver.getEvents();
    assertEquals("Each server should have one occurrence per event type except server failure event", (EventType.values().length - 1), events.size());
    for (EventType event : events) {
        assertEquals("Each event should be recorded exactly once", localServerProvider.serverSize(), sourceObserver.getEventCount(event));
    }
}
Also used : Context(io.mantisrx.runtime.Context) Action0(rx.functions.Action0) Action1(rx.functions.Action1) Server(io.mantisrx.runtime.source.http.LocalServerProvider.Server) EventType(io.mantisrx.runtime.source.http.impl.HttpSourceImpl.HttpSourceEvent.EventType) ServerInfo(mantis.io.reactivex.netty.client.RxClient.ServerInfo) ServerSentEvent(mantis.io.reactivex.netty.protocol.http.sse.ServerSentEvent) Index(io.mantisrx.runtime.source.Index) ByteBuf(io.netty.buffer.ByteBuf) CountDownLatch(java.util.concurrent.CountDownLatch) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) Test(org.junit.Test)

Example 20 with Index

use of io.mantisrx.runtime.source.Index 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());
}
Also used : Context(io.mantisrx.runtime.Context) ServerInfo(mantis.io.reactivex.netty.client.RxClient.ServerInfo) AtomicReference(java.util.concurrent.atomic.AtomicReference) Index(io.mantisrx.runtime.source.Index) HttpClientBuilder(mantis.io.reactivex.netty.protocol.http.client.HttpClientBuilder) ByteBuf(io.netty.buffer.ByteBuf) CountDownLatch(java.util.concurrent.CountDownLatch) HttpServerProvider(io.mantisrx.runtime.source.http.HttpServerProvider) HttpClientFactory(io.mantisrx.runtime.source.http.HttpClientFactory) Test(org.junit.Test)

Aggregations

Index (io.mantisrx.runtime.source.Index)21 Context (io.mantisrx.runtime.Context)19 CountDownLatch (java.util.concurrent.CountDownLatch)18 Test (org.junit.Test)16 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)14 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)13 ServerInfo (mantis.io.reactivex.netty.client.RxClient.ServerInfo)12 Observable (rx.Observable)11 Action1 (rx.functions.Action1)11 ByteBuf (io.netty.buffer.ByteBuf)10 EventType (io.mantisrx.runtime.source.http.impl.HttpSourceImpl.HttpSourceEvent.EventType)9 Action0 (rx.functions.Action0)8 Server (io.mantisrx.runtime.source.http.LocalServerProvider.Server)7 ServerSentEvent (mantis.io.reactivex.netty.protocol.http.sse.ServerSentEvent)7 Set (java.util.Set)5 NoopRegistry (com.netflix.spectator.api.NoopRegistry)4 KafkaUnit (info.batey.kafka.unit.KafkaUnit)4 KafkaAckable (io.mantisrx.connector.kafka.KafkaAckable)4 KafkaSourceParameters (io.mantisrx.connector.kafka.KafkaSourceParameters)4 ParameterTestUtils (io.mantisrx.connector.kafka.ParameterTestUtils)4