def __init__( self, event_dispatcher, logger=None, start_on_init=False, event_queue=None, batch_size=None, flush_interval=None, timeout_interval=None, notification_center=None, ): """ BatchEventProcessor init method to configure event batching. Args: event_dispatcher: Provides a dispatch_event method which if given a URL and params sends a request to it. logger: Optional component which provides a log method to log messages. By default nothing would be logged. start_on_init: Optional boolean param which starts the consumer thread if set to True. Default value is False. event_queue: Optional component which accumulates the events until dispacthed. batch_size: Optional param which defines the upper limit on the number of events in event_queue after which the event_queue will be flushed. flush_interval: Optional floating point number representing time interval in seconds after which event_queue will be flushed. timeout_interval: Optional floating point number representing time interval in seconds before joining the consumer thread. notification_center: Optional instance of notification_center.NotificationCenter. """ self.event_dispatcher = event_dispatcher or default_event_dispatcher self.logger = _logging.adapt_logger(logger or _logging.NoOpLogger()) self.event_queue = event_queue or queue.Queue( maxsize=self._DEFAULT_QUEUE_CAPACITY) self.batch_size = (batch_size if self._validate_instantiation_props( batch_size, 'batch_size', self._DEFAULT_BATCH_SIZE) else self._DEFAULT_BATCH_SIZE) self.flush_interval = (timedelta( seconds=flush_interval) if self._validate_instantiation_props( flush_interval, 'flush_interval', self._DEFAULT_FLUSH_INTERVAL) else timedelta( seconds=self._DEFAULT_FLUSH_INTERVAL)) self.timeout_interval = (timedelta( seconds=timeout_interval) if self._validate_instantiation_props( timeout_interval, 'timeout_interval', self._DEFAULT_TIMEOUT_INTERVAL) else timedelta( seconds=self._DEFAULT_TIMEOUT_INTERVAL)) self.notification_center = notification_center or _notification_center.NotificationCenter( self.logger) self._current_batch = list() if not validator.is_notification_center_valid( self.notification_center): self.logger.error( enums.Errors.INVALID_INPUT.format('notification_center')) self.logger.debug('Creating notification center for use.') self.notification_center = _notification_center.NotificationCenter( self.logger) self.executor = None if start_on_init is True: self.start()
def __init__(self, event_dispatcher, logger=None, notification_center=None): """ ForwardingEventProcessor init method to configure event dispatching. Args: event_dispatcher: Provides a dispatch_event method which if given a URL and params sends a request to it. logger: Optional component which provides a log method to log messages. By default nothing would be logged. notification_center: Optional instance of notification_center.NotificationCenter. """ self.event_dispatcher = event_dispatcher or default_event_dispatcher self.logger = _logging.adapt_logger(logger or _logging.NoOpLogger()) self.notification_center = notification_center or _notification_center.NotificationCenter(self.logger) if not validator.is_notification_center_valid(self.notification_center): self.logger.error(enums.Errors.INVALID_INPUT.format('notification_center')) self.notification_center = _notification_center.NotificationCenter()
def test_add_notification_listener__valid_type(self): """ Test successfully adding a notification listener. """ test_notification_center = notification_center.NotificationCenter() # Test by adding different supported notification listeners. self.assertEqual( 1, test_notification_center.add_notification_listener( enums.NotificationTypes.ACTIVATE, on_activate_listener), ) self.assertEqual( 2, test_notification_center.add_notification_listener( enums.NotificationTypes.OPTIMIZELY_CONFIG_UPDATE, on_config_update_listener, ), ) self.assertEqual( 3, test_notification_center.add_notification_listener( enums.NotificationTypes.DECISION, on_decision_listener), ) self.assertEqual( 4, test_notification_center.add_notification_listener( enums.NotificationTypes.TRACK, on_track_listener), ) self.assertEqual( 5, test_notification_center.add_notification_listener( enums.NotificationTypes.LOG_EVENT, on_log_event_listener), )
def test_clear_all_notification_listeners(self): """ Test that all notification listeners are cleared on using the clear all API. """ test_notification_center = notification_center.NotificationCenter() # Add listeners test_notification_center.add_notification_listener( enums.NotificationTypes.ACTIVATE, on_activate_listener) test_notification_center.add_notification_listener( enums.NotificationTypes.OPTIMIZELY_CONFIG_UPDATE, on_config_update_listener) test_notification_center.add_notification_listener( enums.NotificationTypes.DECISION, on_decision_listener) test_notification_center.add_notification_listener( enums.NotificationTypes.TRACK, on_track_listener) test_notification_center.add_notification_listener( enums.NotificationTypes.LOG_EVENT, on_log_event_listener) # Assert all listeners are there: for notification_type in notification_center.NOTIFICATION_TYPES: self.assertEqual( 1, len(test_notification_center. notification_listeners[notification_type]), ) # Clear all and assert again. test_notification_center.clear_all_notification_listeners() for notification_type in notification_center.NOTIFICATION_TYPES: self.assertEqual( 0, len(test_notification_center. notification_listeners[notification_type]), )
def test_remove_notification_listener__invalid_listener(self): """ Test that removing a invalid notification listener returns False. """ def another_on_activate_listener(*args): pass test_notification_center = notification_center.NotificationCenter() # Add multiple notification listeners. self.assertEqual( 1, test_notification_center.add_notification_listener( enums.NotificationTypes.ACTIVATE, on_activate_listener), ) self.assertEqual( 2, test_notification_center.add_notification_listener( enums.NotificationTypes.DECISION, on_decision_listener), ) self.assertEqual( 3, test_notification_center.add_notification_listener( enums.NotificationTypes.ACTIVATE, another_on_activate_listener), ) self.assertEqual( 4, test_notification_center.add_notification_listener( enums.NotificationTypes.LOG_EVENT, on_log_event_listener), ) # Try removing a listener which does not exist. self.assertFalse( test_notification_center.remove_notification_listener(42))
def test_add_notification_listener__same_listener(self): """ Test that adding same listener again does nothing and returns -1. """ mock_logger = mock.Mock() test_notification_center = notification_center.NotificationCenter( logger=mock_logger) self.assertEqual( 1, test_notification_center.add_notification_listener( enums.NotificationTypes.TRACK, on_track_listener), ) self.assertEqual( 1, len(test_notification_center.notification_listeners[ enums.NotificationTypes.TRACK]), ) # Test that adding same listener again makes no difference. self.assertEqual( -1, test_notification_center.add_notification_listener( enums.NotificationTypes.TRACK, on_track_listener), ) self.assertEqual( 1, len(test_notification_center.notification_listeners[ enums.NotificationTypes.TRACK]), ) mock_logger.error.assert_called_once_with( 'Listener has already been added. Not adding it again.')
def test_clear_notification_listeners(self): """ Test that notification listeners of a certain type are cleared up on using the clear_notification_listeners API. """ test_notification_center = notification_center.NotificationCenter() # Add listeners test_notification_center.add_notification_listener( enums.NotificationTypes.ACTIVATE, on_activate_listener) test_notification_center.add_notification_listener( enums.NotificationTypes.OPTIMIZELY_CONFIG_UPDATE, on_config_update_listener) test_notification_center.add_notification_listener( enums.NotificationTypes.DECISION, on_decision_listener) test_notification_center.add_notification_listener( enums.NotificationTypes.TRACK, on_track_listener) # Assert all listeners are there: for notification_type in notification_center.NOTIFICATION_TYPES: self.assertEqual( 1, len(test_notification_center. notification_listeners[notification_type])) # Clear all of type DECISION. test_notification_center.clear_notification_listeners( enums.NotificationTypes.DECISION) self.assertEqual( 0, len(test_notification_center.notification_listeners[ enums.NotificationTypes.DECISION]))
def test_send_notifications(self): """ Test that send_notifications dispatches notification to the callback(s). """ test_notification_center = notification_center.NotificationCenter() self.listener_called = False test_notification_center.add_notification_listener( enums.NotificationTypes.DECISION, self.set_listener_called_to_true) test_notification_center.send_notifications( enums.NotificationTypes.DECISION) self.assertTrue(self.listener_called)
def test_send_notifications__invalid_notification_type(self): """ Test that send_notifications logs exception when notification_type is invalid. """ mock_logger = mock.Mock() test_notification_center = notification_center.NotificationCenter( logger=mock_logger) test_notification_center.send_notifications( 'invalid_notification_type') mock_logger.error.assert_called_once_with( 'Invalid notification_type: invalid_notification_type provided. ' 'Not triggering any notification.')
def test_remove_notification_listener__valid_listener(self): """ Test that removing a valid notification listener returns True. """ def another_on_activate_listener(*args): pass test_notification_center = notification_center.NotificationCenter() # Add multiple notification listeners. self.assertEqual( 1, test_notification_center.add_notification_listener( enums.NotificationTypes.ACTIVATE, on_activate_listener), ) self.assertEqual( 2, test_notification_center.add_notification_listener( enums.NotificationTypes.DECISION, on_decision_listener), ) self.assertEqual( 3, test_notification_center.add_notification_listener( enums.NotificationTypes.ACTIVATE, another_on_activate_listener), ) self.assertEqual( 2, len(test_notification_center.notification_listeners[ enums.NotificationTypes.ACTIVATE]), ) self.assertEqual( 1, len(test_notification_center.notification_listeners[ enums.NotificationTypes.DECISION]), ) self.assertEqual( 0, len(test_notification_center.notification_listeners[ enums.NotificationTypes.TRACK]), ) self.assertEqual( 0, len(test_notification_center.notification_listeners[ enums.NotificationTypes.LOG_EVENT]), ) # Remove one of the activate listeners and assert. self.assertTrue( test_notification_center.remove_notification_listener(3)) self.assertEqual( 1, len(test_notification_center.notification_listeners[ enums.NotificationTypes.ACTIVATE]), )
def test_clear_notification_listeners__invalid_type(self): """ Test that clear_notification_listener logs error if provided notification type is invalid. """ mock_logger = mock.Mock() test_notification_center = notification_center.NotificationCenter( logger=mock_logger) test_notification_center.clear_notification_listeners( 'invalid_notification_type') mock_logger.error.assert_called_once_with( 'Invalid notification_type: invalid_notification_type provided. ' 'Not removing any listener.')
def test_add_notification_listener__invalid_type(self): """ Test that adding an invalid notification listener fails and returns -1. """ mock_logger = mock.Mock() test_notification_center = notification_center.NotificationCenter( logger=mock_logger) def notif_listener(*args): pass self.assertEqual( -1, test_notification_center.add_notification_listener( 'invalid_notification_type', notif_listener)) mock_logger.error.assert_called_once_with( 'Invalid notification_type: invalid_notification_type provided. ' 'Not adding listener.')
def test_add_notification_listener__multiple_listeners(self): """ Test that multiple listeners of the same type can be successfully added. """ def another_on_activate_listener(*args): pass test_notification_center = notification_center.NotificationCenter() # Test by adding multiple listeners of same type. self.assertEqual( 1, test_notification_center.add_notification_listener( enums.NotificationTypes.ACTIVATE, on_activate_listener)) self.assertEqual( 2, test_notification_center.add_notification_listener( enums.NotificationTypes.ACTIVATE, another_on_activate_listener))
def test_send_notifications__fails(self): """ Test that send_notifications logs exception when call back fails. """ # Defining a listener here which expects 2 arguments. def some_listener(arg_1, arg_2): pass mock_logger = mock.Mock() test_notification_center = notification_center.NotificationCenter( logger=mock_logger) test_notification_center.add_notification_listener( enums.NotificationTypes.ACTIVATE, some_listener) # Not providing any of the 2 expected arguments during send. test_notification_center.send_notifications( enums.NotificationTypes.ACTIVATE) mock_logger.exception.assert_called_once_with( 'Unknown problem when sending "{}" type notification.'.format( enums.NotificationTypes.ACTIVATE))