예제 #1
0
            def signal_child_on_complete(self, ack: Ack, is_stop: bool):
                with source.lock:
                    current_state = state[0]
                    state[0] = WaitOnNextChild(ack)

                if isinstance(current_state, WaitOnNextChild) or isinstance(current_state, Active):
                    ack.subscribe(self.async_upstream_ack)
                elif isinstance(current_state, Cancelled):
                    ack.on_next(Stop())
                    ack.on_completed()
                elif isinstance(current_state, WaitComplete):
                    state_: WaitComplete = current_state
                    if not is_stop:
                        if state_.ex is None:
                            self.send_on_complete()
                        else:
                            observer.on_error(state_.ex)
                    else:
                        scheduler.report_failure(state_.ex)
예제 #2
0
class ConnectableSubscriber(Observer):
    def __init__(self, underlying: Observer, scheduler: SchedulerBase):
        self.underlying = underlying
        self.scheduler = scheduler

        self.root_ack = Ack()
        self.connected_ack = self.root_ack
        self.connected_ref = None
        self.is_connected = False
        self.is_connected_started = False
        self.scheduled_done = False
        self.schedule_error = None
        self.was_canceled = False
        self.queue = Queue()
        self.lock = config['concurrency'].RLock()

    def connect(self):
        with self.lock:
            if not self.is_connected and not self.is_connected_started:
                self.is_connected_started = True

                buffer_was_drained = Ack()

                def on_next(v):
                    if isinstance(v, Continue):
                        self.root_ack.on_next(Continue())
                        self.root_ack.on_completed()
                        source.is_connected = True
                        source.queue = None
                        # source.connected_ack = None
                        # todo: fill in
                    elif isinstance(v, Stop):
                        raise NotImplementedError
                    else:
                        raise NotImplementedError

                buffer_was_drained.subscribe(on_next=on_next)

                source = self

                class CustomObserver(Observer):
                    def __init__(self):
                        self.ack = None

                    def on_next(self, v):
                        ack = source.underlying.on_next(v)
                        self.ack = ack

                        def on_next(v):
                            if isinstance(v, Stop):
                                buffer_was_drained.on_next(v)
                                buffer_was_drained.on_completed()

                        ack.subscribe(on_next=on_next)

                        return ack

                    def on_error(self, err):
                        raise NotImplementedError

                    def on_completed(self):
                        if not source.scheduled_done:
                            if self.ack is None:
                                buffer_was_drained.on_next(Continue())
                                buffer_was_drained.on_completed()
                            else:

                                def on_next(v):
                                    if isinstance(v, Continue):
                                        buffer_was_drained.on_next(Continue())
                                        buffer_was_drained.on_completed()

                                self.ack.subscribe(on_next)
                        elif source.schedule_error is not None:
                            raise NotImplementedError
                        else:
                            source.underlying.on_completed()

                class EmptyObject:
                    pass

                self.queue.put(EmptyObject)
                disposable = IteratorAsObservable(iter(self.queue.get, EmptyObject)) \
                    .subscribe(CustomObserver(), self.scheduler, CurrentThreadScheduler())

                self.connected_ref = buffer_was_drained, disposable
        return self.connected_ref

    def push_first(self, elem):
        with self.lock:
            if self.is_connected or self.is_connected_started:
                throw_exception = True
            elif not self.scheduled_done:
                throw_exception = False
                self.queue.put(elem, block=False)
            else:
                throw_exception = False

        if throw_exception:
            raise Exception(
                'Observer was already connected, so cannot pushFirst')

    def push_first_all(self, cs: Iterable):
        with self.lock:
            if self.is_connected or self.is_connected_started:
                throw_exception = True
            elif not self.scheduled_done:
                throw_exception = False
                for elem in cs:
                    self.queue.put(elem, block=False)
            else:
                throw_exception = False

        if throw_exception:
            raise Exception(
                'Observer was already connected, so cannot pushFirst')

    def push_complete(self):
        with self.lock:
            if self.is_connected or self.is_connected_started:
                throw_exception = True
            elif not self.scheduled_done:
                throw_exception = False
                self.scheduled_done = True
            else:
                throw_exception = False

        if throw_exception:
            raise Exception(
                'Observer was already connected, so cannot pushFirst')

    def push_error(self, ex: Exception):
        with self.lock:
            if self.is_connected or self.is_connected_started:
                throw_exception = True
            elif not self.scheduled_done:
                throw_exception = False
                self.scheduled_done = True
                self.schedule_error = ex
            else:
                throw_exception = False

        if throw_exception:
            raise Exception(
                'Observer was already connected, so cannot pushFirst')

    def on_next(self, elem):
        if not self.is_connected:

            def __(v, _):
                if isinstance(v, Continue):
                    ack = self.underlying.on_next(elem)
                    if isinstance(ack, Continue):
                        return rx.Observable.just(ack)
                    elif isinstance(ack, Stop):
                        raise NotImplementedError
                    else:
                        return ack
                else:
                    return Stop()

            new_ack = Ack()
            self.connected_ack \
                .observe_on(self.scheduler) \
                .flat_map(__) \
                .subscribe(new_ack)
            self.connected_ack = new_ack
            return self.connected_ack
        elif not self.was_canceled:
            ack = self.underlying.on_next(elem)
            return ack
        else:
            return Stop()

    def on_error(self, err):
        def on_next(v):
            if isinstance(v, Continue):
                self.underlying.on_error(err)
        self.connected_ack.observe_on(self.scheduler) \
            .subscribe(on_next=on_next)

    def on_completed(self):
        def on_next(v):
            if isinstance(v, Continue):
                self.underlying.on_completed()
        self.connected_ack.observe_on(self.scheduler) \
            .subscribe(on_next=on_next)
예제 #3
0
        def on_next_right(right):
            ack = Ack()
            upper_ack = None
            has_inner_left_elem = False
            request_left_right = False
            request_right = False

            with self.lock:
                if 0 < inner_left_completed[0]:
                    inner_left_completed[0] -= 1
                    request_right = True
                    upper_ack = Continue()
                    # new_state = self.WaitForLeftOrRight()
                    new_state = state[0]
                elif isinstance(state[0], self.WaitForLeftOrRight):
                    new_state = self.WaitForLeft(right_elem=right,
                                                 right_ack=ack)
                elif isinstance(state[0], self.WaitForRightOrInner):
                    state_: FlatZipObservable.WaitForRightOrInner = state[0]
                    if inner_left_completed[0] == 0:
                        new_state = self.Active(left_ack=state_.left_ack,
                                                right_elem=right,
                                                right_ack=ack,
                                                upper_ack=Continue())
                    else:
                        inner_left_completed[0] -= 1
                        new_state = self.WaitForLeftOrRight()
                elif isinstance(state[0], self.WaitForRight):
                    state_: FlatZipObservable.WaitForRight = state[0]
                    has_inner_left_elem = True
                    left_elem = state_.left_elem
                    left_ack = state_.left_ack
                    inner_left_elem = state_.inner_left_elem
                    inner_left_ack = state_.inner_left_ack
                    new_state = state[0]
                elif isinstance(state[0], source.Completed):
                    return stop_ack
                else:
                    raise NotImplementedError
                state[0] = new_state

            if has_inner_left_elem:
                zipped_elem = self.selector(left_elem, right, inner_left_elem)
                upper_ack = observer.on_next(zipped_elem)

                if isinstance(upper_ack, Stop):
                    with self.lock:
                        state[0] = self.Completed
                        return upper_ack

                request_inner_elem = False
                with self.lock:
                    if 0 < inner_left_completed[0]:
                        # inner left completed, request new left and right
                        new_state = self.WaitForLeftOrRight()
                        request_left_right = True
                    else:
                        # state is the same, change state to active
                        new_state = self.Active(left_ack=left_ack,
                                                right_elem=right,
                                                right_ack=ack,
                                                upper_ack=upper_ack)
                        request_inner_elem = True
                    state[0] = new_state

                if request_inner_elem:
                    if isinstance(upper_ack, Continue) or isinstance(
                            upper_ack, Stop):
                        inner_left_ack.on_next(upper_ack)
                        inner_left_ack.on_completed()
                    else:
                        upper_ack.observe_on(scheduler).subscribe(
                            inner_left_ack)

                if request_left_right:
                    if isinstance(upper_ack, Continue):
                        left_ack.on_next(upper_ack)
                        left_ack.on_completed()
                    else:
                        upper_ack.observe_on(scheduler).subscribe(left_ack)

            if request_left_right or request_right:
                if isinstance(upper_ack, Continue):
                    ack.on_next(upper_ack)
                    ack.on_completed()
                else:
                    upper_ack.observe_on(scheduler).subscribe(ack)

            return ack