async def _async_notify_consumers(self, data): try: # send notification only if is a notification channel is running channels.get_chan(self.FEED_CHANNEL.get_name()) await self.feed_send_coroutine(data) except KeyError: self.logger.error( "Can't send notification data: no initialized channel found")
async def test_remove_consumer(test_channel): consumer = await channels.get_chan(tests.EMPTY_TEST_CHANNEL ).new_consumer(tests.empty_test_callback ) assert channels.get_chan( tests.EMPTY_TEST_CHANNEL).get_consumers() == [consumer] await channels.get_chan(tests.EMPTY_TEST_CHANNEL).remove_consumer(consumer) assert channels.get_chan(tests.EMPTY_TEST_CHANNEL).get_consumers() == []
async def test_register_producer(test_channel): assert channels.get_chan(tests.EMPTY_TEST_CHANNEL).producers == [] producer = tests.EmptyTestProducer(None) await channels.get_chan(tests.EMPTY_TEST_CHANNEL ).register_producer(producer) assert channels.get_chan(tests.EMPTY_TEST_CHANNEL).producers == [producer] channels.get_chan(tests.EMPTY_TEST_CHANNEL).unregister_producer(producer) assert channels.get_chan(tests.EMPTY_TEST_CHANNEL).producers == []
async def send_notification(notification: notifications.Notification) -> None: try: # send notification only if is a notification channel is running channel.get_chan(channels.NotificationChannel.get_name()) await channels.NotificationChannelProducer.instance().send( {"notification": notification}) except KeyError: if len(pending_notifications) < MAX_PENDING_NOTIFICATION: pending_notifications.append(notification)
async def test_get_internal_producer(): class TestChannel(channels.Channel): pass channels.del_chan(tests.TEST_CHANNEL) await util.create_channel_instance(TestChannel, channels.set_chan) with pytest.raises(TypeError): channels.get_chan(tests.TEST_CHANNEL).get_internal_producer() await channels.get_chan(tests.TEST_CHANNEL).stop()
async def test_is_consumers_queue_empty_with_multiple_consumers(synchronized_channel): async def callback(): pass await synchronized_channel.new_consumer(callback) await synchronized_channel.new_consumer(callback) await synchronized_channel.new_consumer(callback, priority_level=2) await synchronized_channel.new_consumer(callback, priority_level=2) await synchronized_channel.new_consumer(callback, priority_level=3) producer = SynchronizedProducerTest(channels.get_chan(TEST_SYNCHRONIZED_CHANNEL)) await producer.run() await producer.send({}) assert not producer.is_consumers_queue_empty(1) assert not producer.is_consumers_queue_empty(2) assert not producer.is_consumers_queue_empty(3) await producer.synchronized_perform_consumers_queue(1, True, 1) assert producer.is_consumers_queue_empty(1) assert not producer.is_consumers_queue_empty(2) assert not producer.is_consumers_queue_empty(3) await producer.synchronized_perform_consumers_queue(2, True, 1) assert producer.is_consumers_queue_empty(1) assert producer.is_consumers_queue_empty(2) assert not producer.is_consumers_queue_empty(3) await producer.synchronized_perform_consumers_queue(2, True, 1) assert not producer.is_consumers_queue_empty(3) await producer.synchronized_perform_consumers_queue(3, True, 1) assert producer.is_consumers_queue_empty(3)
async def test_create_all_subclasses_channel(): class TestChannelClass(channels.Channel): pass class Test1Channel(TestChannelClass): pass class Test2Channel(TestChannelClass): pass def clean_channels(): for channel in copy.deepcopy( channels.ChannelInstances.instance().channels): channels.del_chan(channel) channels.del_chan(tests.TEST_CHANNEL) await util.create_all_subclasses_channel(TestChannelClass, channels.set_chan) assert len(channels.ChannelInstances.instance().channels ) == 3 # (EmptyTestChannel, Test1Channel, Test2Channel) clean_channels() await util.create_all_subclasses_channel(TestChannelClass, channels.set_chan, is_synchronized=True) assert all( channels.get_chan(channel).is_synchronized for channel in channels.ChannelInstances.instance().channels) clean_channels()
async def test_send_producer_without_consumer(): class TestProducer(channel_producer.Producer): async def send(self, data, **kwargs): await super().send(data) await channels.get_chan(tests.TEST_CHANNEL).stop() async def pause(self): pass async def resume(self): pass class TestConsumer(channel_consumer.Consumer): async def consume(self): while not self.should_stop: await self.callback(**(await self.queue.get())) class TestChannel(channels.Channel): PRODUCER_CLASS = TestProducer CONSUMER_CLASS = TestConsumer channels.del_chan(tests.TEST_CHANNEL) await util.create_channel_instance(TestChannel, channels.set_chan) producer = TestProducer(channels.get_chan(tests.TEST_CHANNEL)) await producer.run() await producer.send({})
async def _create_notification_channel_if_not_existing() -> channels.Channel: try: return channels.get_chan(service_channels.NotificationChannel.get_name()) except KeyError: channel = await channel_creator.create_channel_instance(service_channels.NotificationChannel, channels.set_chan) await channel.register_producer(service_channels.NotificationChannelProducer.instance(channel)) return channel
async def test_create_synchronized_channel_instance(): class TestChannel(channels.Channel): pass channels.del_chan(tests.TEST_CHANNEL) await util.create_channel_instance(TestChannel, channels.set_chan, is_synchronized=True) assert channels.get_chan(tests.TEST_CHANNEL).is_synchronized await channels.get_chan(tests.TEST_CHANNEL).stop()
async def test_new_consumer_with_filters(test_channel): consumer = await channels.get_chan(tests.EMPTY_TEST_CHANNEL).new_consumer( tests.empty_test_callback, {"test_key": 1}) assert channels.get_chan( tests.EMPTY_TEST_CHANNEL).get_consumers() == [consumer] assert channels.get_chan( tests.EMPTY_TEST_CHANNEL).get_consumer_from_filters( {}) == [consumer] # returns all if empty assert channels.get_chan( tests.EMPTY_TEST_CHANNEL).get_consumer_from_filters({"test_key": 2}) == [] assert channels.get_chan( tests.EMPTY_TEST_CHANNEL).get_consumer_from_filters({ "test_key": 1, "test2": 2 }) == [] assert channels.get_chan( tests.EMPTY_TEST_CHANNEL).get_consumer_from_filters({"test_key": 1}) == [consumer]
async def test_synchronized_no_tasks(synchronized_channel): async def callback(): pass test_consumer = await synchronized_channel.new_consumer(callback) producer = SynchronizedProducerTest(channels.get_chan(TEST_SYNCHRONIZED_CHANNEL)) await producer.run() assert test_consumer.consume_task is None assert producer.produce_task is None
async def init_consumer_test(): class TestChannel(channels.Channel): PRODUCER_CLASS = tests.EmptyTestProducer CONSUMER_CLASS = tests.EmptyTestConsumer channels.del_chan(tests.TEST_CHANNEL) await util.create_channel_instance(TestChannel, channels.set_chan) producer = tests.EmptyTestProducer(channels.get_chan(tests.TEST_CHANNEL)) await producer.run() return await channels.get_chan(tests.TEST_CHANNEL ).new_consumer(tests.empty_test_callback)
async def test_producer_is_running(): class TestChannel(channels.Channel): PRODUCER_CLASS = tests.EmptyTestProducer channels.del_chan(tests.TEST_CHANNEL) await util.create_channel_instance(TestChannel, channels.set_chan) producer = tests.EmptyTestProducer(channels.get_chan(tests.TEST_CHANNEL)) assert not producer.is_running await producer.run() assert producer.is_running await channels.get_chan(tests.TEST_CHANNEL).stop() assert not producer.is_running
async def initialize(self): try: self.time_manager = backtesting_time.TimeManager(config=self.config) self.time_manager.initialize() self.time_channel = await channel_util.create_channel_instance(backtesting_time.TimeChannel, channels.set_chan, is_synchronized=True) self.time_updater = backtesting_time.TimeUpdater( channels.get_chan(channels_name.OctoBotBacktestingChannelsName.TIME_CHANNEL.value), self) except Exception as e: self.logger.exception(e, True, f"Error when initializing backtesting : {e}.")
async def test_producer_synchronized_perform_consumers_queue_with_one_consumer(synchronized_channel): async def callback(): pass test_consumer = await synchronized_channel.new_consumer(callback) producer = SynchronizedProducerTest(channels.get_chan(TEST_SYNCHRONIZED_CHANNEL)) await producer.run() with mock.patch.object(test_consumer, 'callback', new=mock.AsyncMock()) as mocked_test_consumer_callback: await producer.send({}) await tests.mock_was_not_called(mocked_test_consumer_callback) await producer.synchronized_perform_consumers_queue(1, True, 1) await tests.mock_was_called_once(mocked_test_consumer_callback)
async def internal_consumer(): class TestInternalConsumer(channel_consumer.InternalConsumer): async def perform(self, kwargs): pass class TestChannel(channels.Channel): PRODUCER_CLASS = tests.EmptyTestProducer CONSUMER_CLASS = TestInternalConsumer channels.del_chan(tests.TEST_CHANNEL) await util.create_channel_instance(TestChannel, channels.set_chan) producer = tests.EmptyTestProducer(channels.get_chan(tests.TEST_CHANNEL)) await producer.run() yield TestInternalConsumer() await channels.get_chan(tests.TEST_CHANNEL).stop()
async def test_is_consumers_queue_empty_with_one_consumer(synchronized_channel): async def callback(): pass await synchronized_channel.new_consumer(callback) producer = SynchronizedProducerTest(channels.get_chan(TEST_SYNCHRONIZED_CHANNEL)) await producer.run() await producer.send({}) assert not producer.is_consumers_queue_empty(1) assert not producer.is_consumers_queue_empty(2) await producer.synchronized_perform_consumers_queue(1) assert producer.is_consumers_queue_empty(1) assert producer.is_consumers_queue_empty(2)
async def send_user_command(bot_id, subject, action, data, wait_for_processing=False) -> bool: try: channel = channels.get_chan(channels_names.OctoBotUserChannelsName.USER_COMMANDS_CHANNEL.value) await channel.get_internal_producer().send( bot_id=bot_id, subject=subject, action=action, data=data ) if wait_for_processing: producers = channel.producers if channel.internal_producer is not None: producers.append(channel.internal_producer) await asyncio.gather(*(producer.wait_for_processing() for producer in producers)) return True except KeyError: return False
async def test_producer_pause_resume(): class TestChannel(channels.Channel): PRODUCER_CLASS = channel_producer.Producer channels.del_chan(tests.TEST_CHANNEL) await util.create_channel_instance(TestChannel, channels.set_chan) producer = channel_producer.Producer(channels.get_chan(tests.TEST_CHANNEL)) assert producer.channel.is_paused await producer.pause() assert producer.channel.is_paused await producer.resume() assert not producer.channel.is_paused await producer.pause() assert producer.channel.is_paused await producer.resume() assert not producer.channel.is_paused await channels.get_chan(tests.TEST_CHANNEL).stop()
async def test_pause_producer_without_consumers(): class TestProducer(channel_producer.Producer): async def pause(self): await channels.get_chan(tests.TEST_CHANNEL).stop() async def pause(self): pass async def resume(self): pass class TestChannel(channels.Channel): PRODUCER_CLASS = TestProducer CONSUMER_CLASS = tests.EmptyTestConsumer channels.del_chan(tests.TEST_CHANNEL) await util.create_channel_instance(TestChannel, channels.set_chan) await TestProducer(channels.get_chan(tests.TEST_CHANNEL)).run()
async def test_resume_producer(): class TestSupervisedConsumer(channel_consumer.SupervisedConsumer): pass class TestChannel(channels.Channel): PRODUCER_CLASS = tests.EmptyTestProducer CONSUMER_CLASS = TestSupervisedConsumer channels.del_chan(tests.TEST_CHANNEL) await util.create_channel_instance(TestChannel, channels.set_chan) producer = tests.EmptyTestProducer(channels.get_chan(tests.TEST_CHANNEL)) await producer.run() await channels.get_chan(tests.TEST_CHANNEL).new_consumer(tests.empty_test_callback) await channels.get_chan(tests.TEST_CHANNEL).new_consumer(tests.empty_test_callback) await channels.get_chan(tests.TEST_CHANNEL).new_consumer(tests.empty_test_callback) await producer.send({"data": "test"}) await producer.wait_for_processing() await channels.get_chan(tests.TEST_CHANNEL).stop()
async def test_send_producer_with_consumer(): class TestConsumer(channel_consumer.Consumer): pass class TestChannel(channels.Channel): PRODUCER_CLASS = tests.EmptyTestProducer CONSUMER_CLASS = TestConsumer async def callback(data): assert data == "test" await channels.get_chan(tests.TEST_CHANNEL).stop() channels.del_chan(tests.TEST_CHANNEL) await util.create_channel_instance(TestChannel, channels.set_chan) await channels.get_chan(tests.TEST_CHANNEL).new_consumer(callback) producer = tests.EmptyTestProducer(channels.get_chan(tests.TEST_CHANNEL)) await producer.run() await producer.send({"data": "test"})
async def test_supervised_consumer(): class TestSupervisedConsumer(channel_consumer.SupervisedConsumer): pass class TestChannel(channels.Channel): PRODUCER_CLASS = tests.EmptyTestProducer CONSUMER_CLASS = TestSupervisedConsumer channels.del_chan(tests.TEST_CHANNEL) await util.create_channel_instance(TestChannel, channels.set_chan) producer = tests.EmptyTestProducer(channels.get_chan(tests.TEST_CHANNEL)) await producer.run() consumer = await channels.get_chan(tests.TEST_CHANNEL ).new_consumer(tests.empty_test_callback ) await channels.get_chan(tests.TEST_CHANNEL ).get_internal_producer().send({}) await consumer.queue.join() await channels.get_chan(tests.TEST_CHANNEL).stop()
async def test_producer_synchronized_perform_supervised_consumer_with_processing_empty_queue(synchronized_channel): continue_event = asyncio.Event() calls = [] done_calls = [] async def callback(): calls.append(None) await asyncio.wait_for(continue_event.wait(), 1) done_calls.append(None) async def set_event_task(): continue_event.set() # use supervised consumers synchronized_channel.CONSUMER_CLASS = tests.EmptyTestSupervisedConsumer test_consumer = await synchronized_channel.new_consumer(callback) producer = SynchronizedProducerTest(channels.get_chan(TEST_SYNCHRONIZED_CHANNEL)) await producer.run() await producer.send({}) await test_consumer.run() try: await tests.wait_asyncio_next_cycle() # called already yet assert calls == [None] # call not finished assert done_calls == [] # queue is empty assert test_consumer.queue.qsize() == 0 asyncio.create_task(set_event_task()) # wait for call to finish even though queue is empty => does not work as we are not joining the # current processing await producer.synchronized_perform_consumers_queue(1, False, 1) assert done_calls == [] # wait for call to finish even though queue is empty with join await producer.synchronized_perform_consumers_queue(1, True, 1) # ensure call actually finished (if we did not join the current task, this call would not have finished) assert done_calls == [None] finally: await test_consumer.stop()
async def test_new_consumer_without_filters(test_channel): consumer = await channels.get_chan(tests.EMPTY_TEST_CHANNEL ).new_consumer(tests.empty_test_callback ) assert channels.get_chan( tests.EMPTY_TEST_CHANNEL).get_consumers() == [consumer]
async def test_new_consumer_without_producer(test_channel): await channels.get_chan(tests.EMPTY_TEST_CHANNEL ).new_consumer(tests.empty_test_callback) assert len(channels.get_chan(tests.EMPTY_TEST_CHANNEL).consumers) == 1
async def test_new_consumer_with_consumer_wildcard_filters(test_channel): consumer = await channels.get_chan(tests.EMPTY_TEST_CHANNEL).new_consumer( tests.empty_test_callback, { "test_key": 1, "test_key_2": "abc", "test_key_3": async_channel.CHANNEL_WILDCARD }) assert channels.get_chan( tests.EMPTY_TEST_CHANNEL).get_consumers() == [consumer] assert channels.get_chan( tests.EMPTY_TEST_CHANNEL).get_consumer_from_filters( {}) == [consumer] # returns all if empty assert channels.get_chan( tests.EMPTY_TEST_CHANNEL).get_consumer_from_filters({ "test_key": 1, "test_key_2": "abc" }) == [consumer] assert channels.get_chan( tests.EMPTY_TEST_CHANNEL).get_consumer_from_filters({ "test_key": 1, "test_key_2": "abc", "test_key_3": 45 }) == [consumer] assert channels.get_chan( tests.EMPTY_TEST_CHANNEL).get_consumer_from_filters({ "test_key": 1, "test_key_2": "abc", "test_key_3": async_channel.CHANNEL_WILDCARD }) == [consumer] assert channels.get_chan( tests.EMPTY_TEST_CHANNEL).get_consumer_from_filters({ "test_key": 4, "test_key_2": "bc" }) == [] assert channels.get_chan( tests.EMPTY_TEST_CHANNEL).get_consumer_from_filters({ "test_key": 1, "test_key_2": async_channel.CHANNEL_WILDCARD }) == [consumer] assert channels.get_chan( tests.EMPTY_TEST_CHANNEL).get_consumer_from_filters({"test_key": 1}) == [consumer] assert channels.get_chan( tests.EMPTY_TEST_CHANNEL).get_consumer_from_filters( {"test_key_2": async_channel.CHANNEL_WILDCARD}) == [consumer] assert channels.get_chan( tests.EMPTY_TEST_CHANNEL).get_consumer_from_filters( {"test_key_3": async_channel.CHANNEL_WILDCARD}) == [consumer] assert channels.get_chan( tests.EMPTY_TEST_CHANNEL).get_consumer_from_filters( {"test_key_3": "e"}) == [consumer] assert channels.get_chan( tests.EMPTY_TEST_CHANNEL).get_consumer_from_filters({ "test_key": 3, "test_key_2": async_channel.CHANNEL_WILDCARD }) == [] assert channels.get_chan( tests.EMPTY_TEST_CHANNEL).get_consumer_from_filters({ "test_key": async_channel.CHANNEL_WILDCARD, "test_key_2": "abc" }) == [consumer] assert channels.get_chan( tests.EMPTY_TEST_CHANNEL).get_consumer_from_filters({ "test_key": async_channel.CHANNEL_WILDCARD, "test_key_2": "a" }) == [] assert channels.get_chan( tests.EMPTY_TEST_CHANNEL).get_consumer_from_filters({ "test_key": async_channel.CHANNEL_WILDCARD, "test_key_2": "a", "test_key_3": async_channel.CHANNEL_WILDCARD }) == [] assert channels.get_chan( tests.EMPTY_TEST_CHANNEL).get_consumer_from_filters({ "test_key": async_channel.CHANNEL_WILDCARD, "test_key_2": async_channel.CHANNEL_WILDCARD }) == [consumer]
async def _init_channel(self): channel = channels.get_chan(self.FEED_CHANNEL.get_name()) await channel.register_producer(self)
async def test_new_consumer_with_multiple_consumer_filtering(test_channel): consumers_descriptions = [ { "A": 1, "B": 2, "C": async_channel.CHANNEL_WILDCARD }, # 0 { "A": False, "B": "BBBB", "C": async_channel.CHANNEL_WILDCARD }, # 1 { "A": 3, "B": async_channel.CHANNEL_WILDCARD, "C": async_channel.CHANNEL_WILDCARD }, # 2 { "A": async_channel.CHANNEL_WILDCARD, "B": async_channel.CHANNEL_WILDCARD, "C": async_channel.CHANNEL_WILDCARD }, # 3 { "A": async_channel.CHANNEL_WILDCARD, "B": 2, "C": 1 }, # 4 { "A": True, "B": async_channel.CHANNEL_WILDCARD, "C": async_channel.CHANNEL_WILDCARD }, # 5 { "A": None, "B": None, "C": async_channel.CHANNEL_WILDCARD }, # 6 { "A": "PPP", "B": 1, "C": async_channel.CHANNEL_WILDCARD, "D": 5 }, # 7 { "A": async_channel.CHANNEL_WILDCARD, "B": 2, "C": "ABC" }, # 8 { "A": async_channel.CHANNEL_WILDCARD, "B": True, "C": async_channel.CHANNEL_WILDCARD }, # 9 { "A": async_channel.CHANNEL_WILDCARD, "B": 6, "C": async_channel.CHANNEL_WILDCARD, "D": async_channel.CHANNEL_WILDCARD }, # 10 { "A": async_channel.CHANNEL_WILDCARD, "B": async_channel.CHANNEL_WILDCARD, "C": async_channel.CHANNEL_WILDCARD, "D": async_channel.CHANNEL_WILDCARD }, # 11 { "A": None, "B": False, "C": "LLLL", "D": async_channel.CHANNEL_WILDCARD }, # 12 { "A": None, "B": None, "C": async_channel.CHANNEL_WILDCARD, "D": None }, # 13 { "A": async_channel.CHANNEL_WILDCARD, "B": 2, "C": async_channel.CHANNEL_WILDCARD, "D": None }, # 14 { "A": async_channel.CHANNEL_WILDCARD, "B": [2, 3, 4, 5, 6], "C": async_channel.CHANNEL_WILDCARD, "D": None }, # 15 { "A": async_channel.CHANNEL_WILDCARD, "B": ["A", 5, "G"], "C": async_channel.CHANNEL_WILDCARD, "D": None }, # 16 { "A": [1, 2, 3], "B": 2, "C": async_channel.CHANNEL_WILDCARD, "D": async_channel.CHANNEL_WILDCARD }, # 17 { "A": ["A", "B", "C"], "B": 2, "C": async_channel.CHANNEL_WILDCARD, "D": async_channel.CHANNEL_WILDCARD }, # 18 { "A": async_channel.CHANNEL_WILDCARD, "B": [2], "C": async_channel.CHANNEL_WILDCARD, "D": async_channel.CHANNEL_WILDCARD }, # 19 { "A": async_channel.CHANNEL_WILDCARD, "B": ["B"], "C": async_channel.CHANNEL_WILDCARD, "D": async_channel.CHANNEL_WILDCARD }, # 20 { "A": 18, "B": ["A", "B", "C"], "C": ["---", "9", "#"], "D": async_channel.CHANNEL_WILDCARD }, # 21 { "A": [9, 18], "B": ["B", "C", "D"], "C": ["---", "9", "#", "@", "{"], "D": ["P", "__str__"] } # 22 ] consumers = [ await channels.get_chan(tests.EMPTY_TEST_CHANNEL ).new_consumer(tests.empty_test_callback, consumers_description) for consumers_description in consumers_descriptions ] assert channels.get_chan( tests.EMPTY_TEST_CHANNEL).get_consumers() == consumers assert channels.get_chan( tests.EMPTY_TEST_CHANNEL).get_consumer_from_filters({}) == consumers # Warning : consumer[5] is returned because 1 == True assert channels.get_chan(tests.EMPTY_TEST_CHANNEL).get_consumer_from_filters({"A": 1, "B": "6"}) == \ [consumers[3], consumers[5], consumers[11]] assert channels.get_chan(tests.EMPTY_TEST_CHANNEL).get_consumer_from_filters({"A": async_channel.CHANNEL_WILDCARD, "B": "G", "C": "1A"}) == \ [consumers[2], consumers[3], consumers[5], consumers[11], consumers[16]] assert channels.get_chan( tests.EMPTY_TEST_CHANNEL).get_consumer_from_filters({ "A": async_channel.CHANNEL_WILDCARD, "B": async_channel.CHANNEL_WILDCARD, "C": async_channel.CHANNEL_WILDCARD }) == consumers assert channels.get_chan(tests.EMPTY_TEST_CHANNEL).get_consumer_from_filters({"A": 18, "B": "A", "C": "#"}) == \ [consumers[3], consumers[11], consumers[16], consumers[21]] assert channels.get_chan(tests.EMPTY_TEST_CHANNEL).get_consumer_from_filters({"A": 18, "B": "C", "C": "#", "D": None}) == \ [consumers[11], consumers[21]] assert channels.get_chan(tests.EMPTY_TEST_CHANNEL).get_consumer_from_filters({"A": 18, "B": "C", "C": "^", "D": None}) == \ [consumers[11]] assert channels.get_chan(tests.EMPTY_TEST_CHANNEL).get_consumer_from_filters({"A": 18, "B": "C", "C": "#", "D": "__str__"}) == \ [consumers[11], consumers[21], consumers[22]]