예제 #1
0
    def push_on_next(self, elem, last_to_push: int = None):
        if self.upstream_is_complete or self.downstream_is_complete:
            return Stop()
        else:
            if last_to_push is None:
                with self.lock:
                    to_push = self.items_to_push
                    self.items_to_push += 1
            else:
                to_push = last_to_push

            if self.back_pressured is None:
                if to_push < self.buffer_size:
                    self.queue.put(item=elem)
                    self.push_to_consumer(to_push)
                    return continue_ack
                else:
                    ack = Ack()
                    with self.lock:
                        self.back_pressured = ack
                    self.queue.put(item=elem)
                    self.push_to_consumer(to_push)
                    return ack
            else:
                self.queue.put(item=elem)
                self.push_to_consumer(to_push)
                return self.back_pressured
예제 #2
0
    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()
예제 #3
0
 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()
예제 #4
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)
예제 #5
0
 def on_stop_or_failure_ref(self, err=None):
     if err:
         scheduler.report_failure(err)
     self.signal_child_on_complete(Stop(), is_stop=True)
예제 #6
0
        def on_next_left(left_val):
            # left has been requested because of initial state,
            # or because right is higher than left

            left_elem[0] = left_val
            left_ack[0] = Ack()
            publish_subject[0] = PublishSubject()

            # send next inner observable; subscribe needs to happen immediately
            outer_ack[0] = left_observer[0].on_next(
                (left_val, publish_subject[0]))  # todo: make this private

            with lock:
                has_left_elem[0] = True

                if has_right_elem[0]:
                    has_right = True
                else:
                    # race condition: left element is receieved first
                    has_right = False

            if has_right:
                right_val = right_elem[0]

                if left_is_lower(left_val, right_val):
                    # right is higher than left
                    # send (empty) inner observable and request new left; don't discard right element
                    # inner observable is empty, because left has just been received

                    # discard left element
                    has_left_elem[0] = False
                    left_elem[0] = None

                    # complete (empty) inner observable
                    publish_subject[0].on_completed()

                    # continue next left element after outer acknowledgment
                    return outer_ack[0]
                if left_is_higher(left_val, right_val):
                    # right is lower than left, discard right and request new right
                    # this is possible in initial phase or if is_lower and is_higher are not tight

                    assert right_ack[0] is not None, 'missing acknowledgment'

                    with lock:
                        # avoids completing observer twice

                        # discard right element
                        has_right_elem[0] = False
                        right_elem[0] = None

                        if has_completed[0]:
                            complete_observer = True
                        else:
                            complete_observer = False

                    if complete_observer:
                        left_observer[0].on_completed()
                        right_observer[0].on_completed()
                        return Stop()

                    ack = right_observer[0].on_next((False, right_val))

                    # request new right
                    ack.connect_ack(next_ack=right_ack[0])

                else:
                    # left is equal to right, send right element, request new right

                    with lock:
                        # avoids completing observer twice

                        # discard right element
                        has_right_elem[0] = False
                        right_elem[0] = None

                        if has_completed[0]:
                            complete_observer = True
                        else:
                            complete_observer = False

                    if complete_observer:
                        left_observer[0].on_completed()
                        right_observer[0].on_completed()
                        return Stop()

                    # send right element
                    ack = publish_subject[0].on_next(right_val)
                    ack2 = right_observer[0].on_next((True, right_val))

                    # request new right element
                    ack.connect_ack_2(ack2=ack2, next_ack=right_ack[0])

            return_ack = left_ack[0].merge_ack(outer_ack[0])

            # return left_ack[0]
            return return_ack
예제 #7
0
        def on_next_right(right_val):
            right_elem[0] = right_val
            right_ack[0] = Ack()

            with lock:
                has_right_elem[0] = True

                if has_left_elem[0]:
                    has_left = True
                else:
                    has_left = False

            if has_left:
                left_val = left_elem[0]

                # print('left={}, right={}'.format(left_val, right_val))

                if is_higher(left_val, right_val):
                    # right is higher than left
                    # complete inner observable, discard left and request new left; save right

                    with lock:
                        # avoids completing observer twice

                        # discard left element
                        has_left_elem[0] = False
                        left_elem[0] = None

                        if has_completed[0]:
                            complete_observer = True
                        else:
                            complete_observer = False

                    if complete_observer:
                        left_observer[0].on_completed()
                        right_observer[0].on_completed()
                        return Stop()

                    # complete inner observable
                    publish_subject[0].on_completed()

                    left_ack[0].on_next(continue_ack)
                    left_ack[0].on_completed()

                    return right_ack[0]

                if is_lower(left_val, right_val):
                    # right is lower than left, discard right and request new right
                    # this is possible in initial phase or if is_lower and is_higher are not tight

                    ack = right_observer[0].on_next((False, right_val))

                    # discard right element
                    has_right_elem[0] = False
                    right_elem[0] = None

                    return ack
                else:
                    # left is equal to right, send right element, request new right

                    # discard right element
                    has_right_elem[0] = False
                    right_elem[0] = None

                    # send right element
                    ack = publish_subject[0].on_next(right_val)
                    ack2 = right_observer[0].on_next((True, right_val))

                    return ack.merge_ack(ack2)

            else:
                # no left element has been yet received; only possible in initial phase
                return right_ack[0]
예제 #8
0
        def on_next_left(left):
            # left has been requested because of initial state,
            # or because right is higher than left

            left_elem[0] = left
            left_ack[0] = Ack()

            with lock:
                has_left_elem[0] = True

                if has_right_elem[0]:
                    has_right = True
                else:
                    # race condition: left element is receieved first
                    has_right = False

            if has_right:
                right = right_elem[0]

                if left_is_lower(left, right):
                    # right is higher than left
                    # request new left; don't discard right element

                    # discard left element
                    has_left_elem[0] = False
                    left_elem[0] = None

                    return continue_ack

                if left_is_higher(left, right):
                    # right is lower than left, discard right and request new right
                    # this is possible in initial phase or if is_lower and is_higher are not tight

                    assert right_ack[0] is not None, 'missing acknowledgment'

                    with lock:
                        # avoids completing observer twice

                        # discard right element
                        has_right_elem[0] = False
                        right_elem[0] = None

                        if has_completed[0]:
                            complete_observer = True
                        else:
                            complete_observer = False

                    if complete_observer:
                        # left_observer.on_completed()
                        observer.on_completed()
                        return Stop()

                    right_ack[0].on_next(continue_ack)
                    right_ack[0].on_completed()

                else:
                    # left is equal to right, send right element, request new right

                    with lock:
                        # avoids completing observer twice

                        # discard right element
                        has_right_elem[0] = False
                        right_elem[0] = None

                        if has_completed[0]:
                            complete_observer = True
                        else:
                            complete_observer = False

                    if complete_observer:
                        # left_observer.on_completed()
                        observer.on_completed()
                        return Stop()

                    # send right element
                    ack = observer.on_next(self.selector(left, right))

                    # request new right element
                    ack.connect_ack(right_ack[0])

                    # # request new left element
                    # return ack

            return left_ack[0]
예제 #9
0
        def on_next_right(right):
            right_elem[0] = right
            right_ack[0] = Ack()

            with lock:
                has_right_elem[0] = True

                if has_left_elem[0]:
                    has_left = True
                else:
                    has_left = False

            if has_left:
                left = left_elem[0]

                if right_is_higher(left, right):
                    # right is higher than left
                    # complete inner observable, discard left and request new left; save right

                    with lock:
                        # avoids completing observer twice

                        # discard left element
                        has_left_elem[0] = False
                        left_elem[0] = None

                        if has_completed[0]:
                            complete_observer = True
                        else:
                            complete_observer = False

                    if complete_observer:
                        observer.on_completed()
                        return Stop()

                    left_ack[0].on_next(continue_ack)
                    left_ack[0].on_completed()

                    return right_ack[0]

                if right_is_lower(left, right):
                    # right is lower than left, discard right and request new right
                    # this is possible in initial phase or if is_lower and is_higher are not tight

                    # discard right element
                    has_right_elem[0] = False
                    right_elem[0] = None

                    return continue_ack
                else:
                    # left is equal to right, send right element, request new right

                    # discard right element
                    has_right_elem[0] = False
                    right_elem[0] = None

                    # send right element
                    ack = observer.on_next(self.selector(left, right))

                    return ack

            else:
                # no left element has been yet received; only possible in initial phase
                return right_ack[0]