Search in sources :

Example 11 with GroupedObservable

use of rx.observables.GroupedObservable in project mantis by Netflix.

the class StageExecutors method executeGroupsInParallel.

@SuppressWarnings("unchecked")
private static <K, T, R> Observable<Observable<R>> executeGroupsInParallel(Observable<GroupedObservable<K, T>> go, final Computation computation, final Context context, final long groupTakeUntil) {
    logger.info("initializing {}", computation.getClass().getCanonicalName());
    computation.init(context);
    // from groups to observable
    final Func2<Context, GroupedObservable<K, T>, Observable<R>> c = (Func2<Context, GroupedObservable<K, T>, Observable<R>>) computation;
    return go.lift(new MonitorOperator<>("worker_stage_outer")).map((Func1<GroupedObservable<K, T>, Observable<R>>) group -> c.call(context, GroupedObservableUtils.createGroupedObservable(group.getKey(), group.doOnUnsubscribe(() -> {
        if (groupsExpiredCounter != null)
            groupsExpiredCounter.increment();
    }).timeout(groupTakeUntil, TimeUnit.SECONDS, (Observable<? extends T>) Observable.empty()).subscribeOn(Schedulers.computation()).lift(new MonitorOperator<T>("worker_stage_inner_input")))).lift(new MonitorOperator("worker_stage_inner_output")));
}
Also used : Context(io.mantisrx.runtime.Context) Index(io.mantisrx.runtime.source.Index) StageConfig(io.mantisrx.runtime.StageConfig) MantisRxSingleThreadScheduler(io.mantisrx.runtime.scheduler.MantisRxSingleThreadScheduler) MetricsRegistry(io.mantisrx.common.metrics.MetricsRegistry) LoggerFactory(org.slf4j.LoggerFactory) Action1(rx.functions.Action1) Observable(rx.Observable) Computation(io.mantisrx.runtime.computation.Computation) ServiceRegistry(io.mantisrx.server.core.ServiceRegistry) Func1(rx.functions.Func1) Func2(rx.functions.Func2) GroupToGroup(io.mantisrx.runtime.GroupToGroup) GroupedObservableUtils(io.reactivx.mantis.operators.GroupedObservableUtils) Schedulers(rx.schedulers.Schedulers) GroupToScalar(io.mantisrx.runtime.GroupToScalar) RxMetrics(io.reactivex.mantis.remote.observable.RxMetrics) KeyToScalar(io.mantisrx.runtime.KeyToScalar) Metrics(io.mantisrx.common.metrics.Metrics) Counter(io.mantisrx.common.metrics.Counter) Groups(io.mantisrx.runtime.Groups) Logger(org.slf4j.Logger) RxThreadFactory(rx.internal.util.RxThreadFactory) ScalarToKey(io.mantisrx.runtime.ScalarToKey) SourceHolder(io.mantisrx.runtime.SourceHolder) KeyToKey(io.mantisrx.runtime.KeyToKey) Context(io.mantisrx.runtime.Context) STAGE_CONCURRENCY(io.mantisrx.runtime.parameter.ParameterUtils.STAGE_CONCURRENCY) TimeUnit(java.util.concurrent.TimeUnit) GroupedObservable(rx.observables.GroupedObservable) ScalarToScalar(io.mantisrx.runtime.ScalarToScalar) Action0(rx.functions.Action0) ScalarToGroup(io.mantisrx.runtime.ScalarToGroup) SinkHolder(io.mantisrx.runtime.SinkHolder) MantisMarker(io.mantisrx.runtime.markers.MantisMarker) MantisGroup(io.mantisrx.common.MantisGroup) MonitorOperator(io.mantisrx.common.metrics.rx.MonitorOperator) MonitorOperator(io.mantisrx.common.metrics.rx.MonitorOperator) Observable(rx.Observable) GroupedObservable(rx.observables.GroupedObservable) GroupedObservable(rx.observables.GroupedObservable) Func2(rx.functions.Func2)

Example 12 with GroupedObservable

use of rx.observables.GroupedObservable in project mantis by Netflix.

the class StageExecutorsGroupByTest method testExecuteSource.

@SuppressWarnings({ "rawtypes", "unchecked" })
@Test
public void testExecuteSource() {
    TestGroupByJob provider = new TestGroupByJob();
    Job<Pair> job = provider.getJobInstance();
    List<StageConfig<?, ?>> stages = job.getStages();
    PortSelectorWithinRange portSelector = new PortSelectorWithinRange(8000, 9000);
    int serverPort = portSelector.acquirePort();
    WorkerPublisher producer = new WorkerPublisherRemoteObservable(serverPort, null, Observable.just(1), null);
    // execute source
    BehaviorSubject<Integer> workersInStageOneObservable = BehaviorSubject.create(1);
    StageExecutors.executeSource(0, job.getSource(), stages.get(0), producer, new Context(), workersInStageOneObservable);
    ConnectToGroupedObservable<String, Integer> config = new ConnectToGroupedObservable.Builder<String, Integer>().slotId("0").host("localhost").port(serverPort).keyDecoder(Codecs.string()).valueDecoder(Codecs.integer()).build();
    Iterator<GroupedObservable<String, Integer>> iter = RemoteObservable.connect(config).getObservable().toBlocking().getIterator();
    Assert.assertTrue(iter.hasNext());
    // verify numbers are grouped by even/odd
    // even is first due to zero
    GroupedObservable<String, Integer> even = iter.next();
    Assert.assertEquals("even", even.getKey());
    Iterator<Integer> evenIter = even.toBlocking().getIterator();
    Assert.assertEquals(0, evenIter.next().intValue());
    Assert.assertEquals(2, evenIter.next().intValue());
    Assert.assertEquals(4, evenIter.next().intValue());
    Assert.assertEquals(6, evenIter.next().intValue());
    GroupedObservable<String, Integer> odd = iter.next();
    Assert.assertEquals("odd", odd.getKey());
    Iterator<Integer> oddIter = odd.toBlocking().getIterator();
    Assert.assertEquals(1, oddIter.next().intValue());
    Assert.assertEquals(3, oddIter.next().intValue());
    Assert.assertEquals(5, oddIter.next().intValue());
    Assert.assertEquals(7, oddIter.next().intValue());
    // should only have two groups
    Assert.assertEquals(false, iter.hasNext());
}
Also used : Context(io.mantisrx.runtime.Context) PortSelectorWithinRange(io.reactivex.mantis.remote.observable.PortSelectorWithinRange) StageConfig(io.mantisrx.runtime.StageConfig) Endpoint(io.mantisrx.common.network.Endpoint) ConnectToGroupedObservable(io.reactivex.mantis.remote.observable.ConnectToGroupedObservable) ServeGroupedObservable(io.reactivex.mantis.remote.observable.ServeGroupedObservable) GroupedObservable(rx.observables.GroupedObservable) Test(org.junit.Test)

Example 13 with GroupedObservable

use of rx.observables.GroupedObservable in project mantis by Netflix.

the class StageExecutorsGroupByTest method testExecuteIntermediatStage.

@SuppressWarnings({ "rawtypes", "unchecked" })
@Test
public void testExecuteIntermediatStage() throws InterruptedException {
    // Note, this test has a timing issue, client starts
    // sending data before server is ready, resulting
    // in a RST (connection reset by peer)
    TestGroupByJob provider = new TestGroupByJob();
    Job<Pair> job = provider.getJobInstance();
    List<StageConfig<?, ?>> stages = job.getStages();
    PortSelectorWithinRange portSelector = new PortSelectorWithinRange(8000, 9000);
    final int publishPort = portSelector.acquirePort();
    final int consumerPort = portSelector.acquirePort();
    Observable<Observable<GroupedObservable<String, Integer>>> go = Observable.just(Observable.range(0, 10).groupBy(new Func1<Integer, String>() {

        @Override
        public String call(Integer t1) {
            if ((t1 % 2) == 0) {
                return "even";
            } else {
                return "odd";
            }
        }
    }));
    // mimic previous stage with a server
    ServeGroupedObservable<String, Integer> config = new ServeGroupedObservable.Builder<String, Integer>().keyEncoder(Codecs.string()).valueEncoder(Codecs.integer()).observable(go).build();
    RemoteRxServer server = new RemoteRxServer.Builder().addObservable(config).port(consumerPort).build();
    server.start();
    EndpointInjector staticEndpoints = new EndpointInjector() {

        @Override
        public Observable<EndpointChange> deltas() {
            return Observable.create(new OnSubscribe<EndpointChange>() {

                @Override
                public void call(Subscriber<? super EndpointChange> subscriber) {
                    subscriber.onNext(new EndpointChange(EndpointChange.Type.add, new Endpoint("localhost", consumerPort, "0")));
                    subscriber.onNext(new EndpointChange(EndpointChange.Type.add, new Endpoint("localhost", consumerPort, "1")));
                    subscriber.onCompleted();
                }
            });
        }
    };
    WorkerConsumer consumer = new WorkerConsumerRemoteObservable(null, staticEndpoints);
    WorkerPublisher producer = new WorkerPublisherRemoteObservable(publishPort, null, Observable.just(1), null);
    // execute source
    StageExecutors.executeIntermediate(consumer, stages.get(1), producer, new Context());
    ConnectToGroupedObservable<String, Integer> connectConfig = new ConnectToGroupedObservable.Builder<String, Integer>().host("localhost").port(publishPort).keyDecoder(Codecs.string()).valueDecoder(Codecs.integer()).build();
    Iterator<GroupedObservable<String, Integer>> iter = RemoteObservable.connect(connectConfig).getObservable().toBlocking().getIterator();
    // verify numbers are grouped by even/odd
    // even is first due to zero
    GroupedObservable<String, Integer> even = iter.next();
    Assert.assertEquals("even", even.getKey());
    Iterator<Integer> evenIter = even.toBlocking().getIterator();
    Assert.assertEquals(0, evenIter.next().intValue());
    Assert.assertEquals(4, evenIter.next().intValue());
    Assert.assertEquals(16, evenIter.next().intValue());
    Assert.assertEquals(36, evenIter.next().intValue());
    GroupedObservable<String, Integer> odd = iter.next();
    Assert.assertEquals("odd", odd.getKey());
    Iterator<Integer> oddIter = odd.toBlocking().getIterator();
    Assert.assertEquals(1, oddIter.next().intValue());
    Assert.assertEquals(9, oddIter.next().intValue());
    Assert.assertEquals(25, oddIter.next().intValue());
    Assert.assertEquals(49, oddIter.next().intValue());
    // should only have two groups
    Assert.assertEquals(false, iter.hasNext());
}
Also used : EndpointChange(io.reactivex.mantis.remote.observable.EndpointChange) PortSelectorWithinRange(io.reactivex.mantis.remote.observable.PortSelectorWithinRange) ConnectToGroupedObservable(io.reactivex.mantis.remote.observable.ConnectToGroupedObservable) Endpoint(io.mantisrx.common.network.Endpoint) Func1(rx.functions.Func1) Context(io.mantisrx.runtime.Context) RemoteRxServer(io.reactivex.mantis.remote.observable.RemoteRxServer) StageConfig(io.mantisrx.runtime.StageConfig) Endpoint(io.mantisrx.common.network.Endpoint) ConnectToGroupedObservable(io.reactivex.mantis.remote.observable.ConnectToGroupedObservable) ServeGroupedObservable(io.reactivex.mantis.remote.observable.ServeGroupedObservable) RemoteObservable(io.reactivex.mantis.remote.observable.RemoteObservable) Observable(rx.Observable) GroupedObservable(rx.observables.GroupedObservable) EndpointInjector(io.reactivex.mantis.remote.observable.EndpointInjector) ConnectToGroupedObservable(io.reactivex.mantis.remote.observable.ConnectToGroupedObservable) ServeGroupedObservable(io.reactivex.mantis.remote.observable.ServeGroupedObservable) GroupedObservable(rx.observables.GroupedObservable) Test(org.junit.Test)

Example 14 with GroupedObservable

use of rx.observables.GroupedObservable in project mantis by Netflix.

the class ObservableTrigger method groupTrigger.

private static <K, V> PushTrigger<KeyValuePair<K, V>> groupTrigger(final String name, final Observable<GroupedObservable<K, V>> o, final Action0 doOnComplete, final Action1<Throwable> doOnError, final long groupExpirySeconds, final Func1<K, byte[]> keyEncoder, final HashFunction hashFunction) {
    final AtomicReference<Subscription> subRef = new AtomicReference<>();
    final Gauge subscriptionActive;
    Metrics metrics = new Metrics.Builder().name("ObservableTrigger_" + name).addGauge("subscriptionActive").build();
    subscriptionActive = metrics.getGauge("subscriptionActive");
    Action1<MonitoredQueue<KeyValuePair<K, V>>> doOnStart = new Action1<MonitoredQueue<KeyValuePair<K, V>>>() {

        @Override
        public void call(final MonitoredQueue<KeyValuePair<K, V>> queue) {
            subRef.set(o.observeOn(Schedulers.computation()).doOnSubscribe(() -> {
                logger.info("Subscription is ACTIVE for observable trigger with name: " + name);
                subscriptionActive.set(1);
            }).doOnUnsubscribe(() -> {
                logger.info("Subscription is INACTIVE for observable trigger with name: " + name);
                subscriptionActive.set(0);
            }).flatMap((final GroupedObservable<K, V> group) -> {
                final byte[] keyBytes = keyEncoder.call(group.getKey());
                final long keyBytesHashed = hashFunction.computeHash(keyBytes);
                return group.timeout(groupExpirySeconds, TimeUnit.SECONDS, (Observable<? extends V>) Observable.empty()).lift(new DisableBackPressureOperator<V>()).buffer(250, TimeUnit.MILLISECONDS).filter((List<V> t1) -> t1 != null && !t1.isEmpty()).map((List<V> list) -> {
                    List<KeyValuePair<K, V>> keyPairList = new ArrayList<>(list.size());
                    for (V data : list) {
                        keyPairList.add(new KeyValuePair<K, V>(keyBytesHashed, keyBytes, data));
                    }
                    return keyPairList;
                });
            }).subscribe((List<KeyValuePair<K, V>> list) -> {
                for (KeyValuePair<K, V> data : list) {
                    queue.write(data);
                }
            }, (Throwable e) -> {
                logger.warn("Observable used to push data errored, on server with name: " + name, e);
                if (doOnError != null) {
                    doOnError.call(e);
                }
            }, () -> {
                logger.info("Observable used to push data completed, on server with name: " + name);
                if (doOnComplete != null) {
                    doOnComplete.call();
                }
            }));
        }
    };
    Action1<MonitoredQueue<KeyValuePair<K, V>>> doOnStop = new Action1<MonitoredQueue<KeyValuePair<K, V>>>() {

        @Override
        public void call(MonitoredQueue<KeyValuePair<K, V>> t1) {
            if (subRef.get() != null) {
                logger.warn("Connections from next stage has dropped to 0. Do not propagate unsubscribe");
            // subRef.get().unsubscribe();
            }
        }
    };
    return new PushTrigger<>(doOnStart, doOnStop, metrics);
}
Also used : DisableBackPressureOperator(io.reactivx.mantis.operators.DisableBackPressureOperator) Action1(rx.functions.Action1) ArrayList(java.util.ArrayList) AtomicReference(java.util.concurrent.atomic.AtomicReference) Gauge(io.mantisrx.common.metrics.Gauge) Metrics(io.mantisrx.common.metrics.Metrics) ArrayList(java.util.ArrayList) List(java.util.List) Subscription(rx.Subscription) GroupedObservable(rx.observables.GroupedObservable)

Example 15 with GroupedObservable

use of rx.observables.GroupedObservable in project mantis by Netflix.

the class DynamicConnectionSet method observables.

public Observable<Observable<T>> observables() {
    return endpointInjector.deltas().doOnCompleted(() -> logger.info("onComplete on injector deltas")).doOnError(t -> logger.error("caught unexpected error {}", t.getMessage(), t)).doOnSubscribe(new Action0() {

        @Override
        public void call() {
            logger.info("Subscribing, clearing active connection set");
            resetActiveConnections();
        }
    }).groupBy(new Func1<EndpointChange, String>() {

        @Override
        public String call(EndpointChange t1) {
            return Endpoint.uniqueHost(t1.getEndpoint().getHost(), t1.getEndpoint().getPort(), t1.getEndpoint().getSlotId());
        }
    }).flatMap(new Func1<GroupedObservable<String, EndpointChange>, Observable<Observable<T>>>() {

        @Override
        public Observable<Observable<T>> call(final GroupedObservable<String, EndpointChange> group) {
            final PublishSubject<Integer> closeConnectionTrigger = PublishSubject.create();
            return group.doOnNext(new Action1<EndpointChange>() {

                @Override
                public void call(EndpointChange change) {
                    // side effect to force complete
                    if (EndpointChange.Type.complete == change.getType() && activeConnectionsContains(group.getKey(), change.getEndpoint())) {
                        logger.info("Received complete request, removing connection from active set, " + change.getEndpoint().getHost() + " port: " + change.getEndpoint().getPort() + " id: " + change.getEndpoint().getSlotId());
                        forceCompletedConnections.increment();
                        removeConnection(group.getKey(), change.getEndpoint());
                        closeConnectionTrigger.onNext(1);
                    }
                }
            }).filter(new Func1<EndpointChange, Boolean>() {

                @Override
                public Boolean call(EndpointChange change) {
                    // active connection check is to ensure
                    // latent adds are not allowed.  This can
                    // occur if dynamicConnection set
                    // and reconciliator are chained together.
                    // Reconciliator will "see" changes
                    // before dynamic connection set add will
                    // assume connection is missing from set
                    boolean contains = activeConnectionsContains(group.getKey(), change.getEndpoint());
                    if (contains) {
                        logger.info("Skipping latent add for endpoint, already in active set: " + change);
                    }
                    return EndpointChange.Type.add == change.getType() && !contains;
                }
            }).map(new Func1<EndpointChange, Observable<T>>() {

                @Override
                public Observable<T> call(final EndpointChange toAdd) {
                    logger.info("Received add request, adding connection to active set, " + toAdd.getEndpoint().getHost() + " port: " + toAdd.getEndpoint().getPort() + ", with client id: " + toAdd.getEndpoint().getSlotId());
                    addConnection(group.getKey(), toAdd.getEndpoint());
                    Action0 disconnectCallback = new Action0() {

                        @Override
                        public void call() {
                            int timeToWait = random.nextInt((maxTimeoutOnUnexpectedTerminateSec - minTimeoutOnUnexpectedTerminateSec) + 1) + minTimeoutOnUnexpectedTerminateSec;
                            logger.info("Connection disconnected, waiting " + timeToWait + " seconds before removing from active set of connections: " + toAdd);
                            Observable.timer(timeToWait, TimeUnit.SECONDS).doOnCompleted(new Action0() {

                                @Override
                                public void call() {
                                    logger.warn("Removing connection from active set, " + toAdd);
                                    closedConnections.increment();
                                    removeConnection(group.getKey(), toAdd.getEndpoint());
                                }
                            }).subscribe();
                        }
                    };
                    RemoteRxConnection<T> connection = toObservableFunc.call(toAdd.getEndpoint(), disconnectCallback, closeConnectionTrigger);
                    return connection.getObservable().doOnCompleted(toAdd.getEndpoint().getCompletedCallback()).doOnError(toAdd.getEndpoint().getErrorCallback());
                }
            });
        }
    });
}
Also used : SpscArrayQueue(org.jctools.queues.SpscArrayQueue) Logger(org.slf4j.Logger) ReentrantLock(java.util.concurrent.locks.ReentrantLock) Endpoint(io.mantisrx.common.network.Endpoint) LoggerFactory(org.slf4j.LoggerFactory) Set(java.util.Set) HashMap(java.util.HashMap) Random(java.util.Random) ConnectionSet(io.reactivex.mantis.remote.observable.reconciliator.ConnectionSet) Observer(rx.Observer) Action1(rx.functions.Action1) Observable(rx.Observable) HashSet(java.util.HashSet) TimeUnit(java.util.concurrent.TimeUnit) Lock(java.util.concurrent.locks.Lock) Func1(rx.functions.Func1) GroupedObservable(rx.observables.GroupedObservable) Action0(rx.functions.Action0) Func3(rx.functions.Func3) Gauge(io.mantisrx.common.metrics.Gauge) Map(java.util.Map) MantisGroup(io.mantisrx.common.MantisGroup) Metrics(io.mantisrx.common.metrics.Metrics) PublishSubject(rx.subjects.PublishSubject) Action0(rx.functions.Action0) Action1(rx.functions.Action1) Observable(rx.Observable) GroupedObservable(rx.observables.GroupedObservable) Endpoint(io.mantisrx.common.network.Endpoint) PublishSubject(rx.subjects.PublishSubject) Func1(rx.functions.Func1) GroupedObservable(rx.observables.GroupedObservable)

Aggregations

GroupedObservable (rx.observables.GroupedObservable)23 Func1 (rx.functions.Func1)16 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)13 Test (org.junit.Test)13 Observable (rx.Observable)13 Action0 (rx.functions.Action0)10 CountDownLatch (java.util.concurrent.CountDownLatch)9 ArrayList (java.util.ArrayList)7 Action1 (rx.functions.Action1)6 List (java.util.List)4 Notification (rx.Notification)4 MantisGroup (io.mantisrx.common.MantisGroup)3 Metrics (io.mantisrx.common.metrics.Metrics)3 Endpoint (io.mantisrx.common.network.Endpoint)3 Context (io.mantisrx.runtime.Context)3 StageConfig (io.mantisrx.runtime.StageConfig)3 TimeUnit (java.util.concurrent.TimeUnit)3 PluginTestVerifier (com.navercorp.pinpoint.bootstrap.plugin.test.PluginTestVerifier)2 Gauge (io.mantisrx.common.metrics.Gauge)2 ConnectToGroupedObservable (io.reactivex.mantis.remote.observable.ConnectToGroupedObservable)2