Exemple #1
0
def test_exception_in_observer_doesnt_break_connection_nor_other_observers(
        buffer_transport_class):
    from moler.threaded_moler_connection import ThreadedMolerConnection

    moler_conn = ThreadedMolerConnection()
    moler_received_data = []

    def failing_observer(data):
        raise Exception("Fail inside observer")

    def one_time_observer(data, time_recv):
        moler_received_data.append(data)
        moler_conn.unsubscribe(observer=one_time_observer,
                               connection_closed_handler=do_nothing_func)

    moler_conn.subscribe(observer=failing_observer,
                         connection_closed_handler=do_nothing_func)
    moler_conn.subscribe(observer=one_time_observer,
                         connection_closed_handler=do_nothing_func)

    used_io = buffer_transport_class(
        moler_connection=moler_conn)  # external-IO internally sets .how2send
    used_io.write(input_bytes=b"data 1")  # inject to buffer for next line read
    used_io.read()
    moler_conn.unsubscribe(observer=failing_observer,
                           connection_closed_handler=do_nothing_func)
    MolerTest.sleep(1, True)  # Processing in separate thread so have to wait.

    assert b"data 1" in moler_received_data
Exemple #2
0
def test_repeated_unsubscription_does_nothing_but_logs_warning(buffer_transport_class):
    """
    Because of possible different concurrency models (and their races)
    we don't want to raise exception when there is already
    "no such subscription" - just put warning to logs
    """
    import time
    from moler.threaded_moler_connection import ThreadedMolerConnection

    moler_conn = ThreadedMolerConnection()
    moler_received_data = []

    def one_time_observer(data, time_recv):
        moler_received_data.append(data)
        moler_conn.unsubscribe(observer=one_time_observer, connection_closed_handler=do_nothing_func)

    moler_conn.subscribe(observer=one_time_observer, connection_closed_handler=do_nothing_func)
    # subscribe fires new thread via ObserverThreadWrapper
    # that thread pushes data: moler-connection.notify_observers() --> queue --> one_time_observer()

    used_io = buffer_transport_class(moler_connection=moler_conn)  # external-IO internally sets .how2send
    used_io.write(input_bytes=b"data 1")  # inject to buffer for next line read
    used_io.read()
    time.sleep(0.2)  # allow threads switch to let ObserverThreadWrapper push data into one_time_observer()
    moler_conn.unsubscribe(observer=one_time_observer, connection_closed_handler=do_nothing_func)  # TODO: check
    # warning in logs (when we set logging system)
    used_io.write(input_bytes=b"data 2")  # inject to buffer for next line read
    used_io.read()

    MolerTest.sleep(1, True)  # Processing in separate thread so have to wait.

    assert b"data 1" in moler_received_data
    assert b"data 2" not in moler_received_data  # because of unsubscription during notification
def ping_observing_task(address, ping_ip):
    logger = logging.getLogger('moler.user.app-code')
    net_addr = 'tcp://{}:{}'.format(*address)

    # Lowest layer of Moler's usage (you manually glue all elements):
    # 1. create observers
    net_down_detector = NetworkDownDetector(ping_ip)
    net_drop_found = False
    net_up_detector = NetworkUpDetector(ping_ip)
    moler_conn = ThreadedMolerConnection(
        decoder=lambda data: data.decode("utf-8"))
    # 2. virtually "start" observer by making it data-listener
    moler_conn.subscribe(net_down_detector.data_received)

    info = '{} on {} using {}'.format(ping_ip, net_addr, net_down_detector)
    logger.debug('observe ' + info)
    for _ in tcp_connection(address, moler_conn):
        # anytime new data comes it may change status of observer
        if not net_drop_found and net_down_detector.done():
            net_drop_found = True
            net_down_time = net_down_detector.result()
            timestamp = time.strftime("%H:%M:%S",
                                      time.localtime(net_down_time))
            logger.debug('Network {} is down from {}'.format(
                ping_ip, timestamp))
            # 3. virtually "stop" that observer
            moler_conn.unsubscribe(net_down_detector.data_received)
            # 4. and start subsequent one (to know when net is back "up")
            info = '{} on {} using {}'.format(ping_ip, net_addr,
                                              net_up_detector)
            logger.debug('observe ' + info)
            moler_conn.subscribe(net_up_detector.data_received)
        if net_up_detector.done():
            net_up_time = net_up_detector.result()
            timestamp = time.strftime("%H:%M:%S", time.localtime(net_up_time))
            logger.debug('Network {} is back "up" from {}'.format(
                ping_ip, timestamp))
            # 5. virtually "stop" that observer
            moler_conn.unsubscribe(net_up_detector.data_received)
            break
Exemple #4
0
def test_single_unsubscription_doesnt_impact_other_subscribers():
    from moler.threaded_moler_connection import ThreadedMolerConnection

    class TheObserver(object):
        def __init__(self):
            self.received_data = []

        def on_new_data(self, data, time_recv):
            self.received_data.append(data)

    observer1 = TheObserver()
    observer2 = TheObserver()

    function_received_data = []

    def raw_fun1(data, time_recv):
        function_received_data.append(data)

    def raw_fun2(data, time_recv):
        function_received_data.append(data)

    class TheCallableClass(object):
        def __init__(self):
            self.received_data = []

        def __call__(self, data, time_recv):
            self.received_data.append(data)

    callable1 = TheCallableClass()
    callable2 = TheCallableClass()

    moler_conn = ThreadedMolerConnection()
    moler_conn.subscribe(observer=observer1.on_new_data, connection_closed_handler=do_nothing_func)
    moler_conn.subscribe(observer=observer2.on_new_data, connection_closed_handler=do_nothing_func)
    moler_conn.subscribe(observer=observer2.on_new_data, connection_closed_handler=do_nothing_func)
    moler_conn.unsubscribe(observer=observer1.on_new_data, connection_closed_handler=do_nothing_func)
    moler_conn.unsubscribe(observer=observer1.on_new_data, connection_closed_handler=do_nothing_func)

    moler_conn.subscribe(observer=raw_fun1, connection_closed_handler=do_nothing_func)
    moler_conn.subscribe(observer=raw_fun2, connection_closed_handler=do_nothing_func)
    moler_conn.subscribe(observer=raw_fun2, connection_closed_handler=do_nothing_func)
    moler_conn.unsubscribe(observer=raw_fun1, connection_closed_handler=do_nothing_func)

    moler_conn.subscribe(observer=callable1, connection_closed_handler=do_nothing_func)
    moler_conn.subscribe(observer=callable2, connection_closed_handler=do_nothing_func)
    moler_conn.subscribe(observer=callable2, connection_closed_handler=do_nothing_func)
    moler_conn.unsubscribe(observer=callable1, connection_closed_handler=do_nothing_func)

    moler_conn.data_received("incoming data", datetime.datetime.now())
    MolerTest.sleep(1, True)  # Processing in separate thread so have to wait.

    assert observer1.received_data == []
    assert observer2.received_data == ["incoming data"]

    assert function_received_data == ["incoming data"]

    assert callable1.received_data == []
    assert callable2.received_data == ["incoming data"]