예제 #1
0
def uwsgi_update_segments(user_config):
    """
    Update segments task.

    :param user_config: User-provided configuration.
    :type user_config: dict
    """
    config = _get_config(user_config)
    seconds = config['segmentsRefreshRate']
    segment_sync_task = SegmentSynchronizationTask(
        SegmentsAPI(
            HttpClient(1500, config.get('sdk_url'), config.get('events_url')),
            config['apikey']),
        UWSGISegmentStorage(get_uwsgi()),
        None,  # Split sotrage not needed, segments provided manually,
        None,  # Period not needed, task executed manually
        None  # Flag not needed, never consumed or set.
    )

    pool = workerpool.WorkerPool(20, segment_sync_task._update_segment)  #pylint: disable=protected-access
    pool.start()
    split_storage = UWSGISplitStorage(get_uwsgi())
    while True:
        try:
            for split in split_storage.get_all_splits():
                for segment_name in split.get_segment_names():
                    pool.submit_work(segment_name)
            time.sleep(seconds)
        except Exception:  #pylint: disable=broad-except
            _LOGGER.error('Error updating segments')
            _LOGGER.debug('Error: ', exc_info=True)
예제 #2
0
def uwsgi_update_segments(user_config):
    """
    Update segments task.

    :param user_config: User-provided configuration.
    :type user_config: dict
    """
    config = _get_config(user_config)
    seconds = config['segmentsRefreshRate']
    metadata = get_metadata(config)
    segment_sync = SegmentSynchronizer(
        SegmentsAPI(
            HttpClient(1500, config.get('sdk_url'), config.get('events_url')),
            config['apikey'], metadata),
        UWSGISplitStorage(get_uwsgi()),
        UWSGISegmentStorage(get_uwsgi()),
    )

    pool = workerpool.WorkerPool(20, segment_sync.synchronize_segment)  # pylint: disable=protected-access
    pool.start()
    split_storage = UWSGISplitStorage(get_uwsgi())
    while True:
        try:
            for segment_name in split_storage.get_segment_names():
                pool.submit_work(segment_name)
            time.sleep(seconds)
        except Exception:  # pylint: disable=broad-except
            _LOGGER.error('Error updating segments')
            _LOGGER.debug('Error: ', exc_info=True)
예제 #3
0
 def test_gauges(self):
     """Test storing and popping gauges."""
     storage = UWSGITelemetryStorage(get_uwsgi(True))
     storage.put_gauge('some_gauge1', 123)
     storage.put_gauge('some_gauge2', 456)
     assert storage.pop_gauges() == {'some_gauge1': 123, 'some_gauge2': 456}
     assert storage.pop_gauges() == {}
예제 #4
0
    def test_get_all_splits(self, mocker):
        """Test fetching all splits."""
        uwsgi = get_uwsgi(True)
        storage = UWSGISplitStorage(uwsgi)
        split_1 = mocker.Mock(spec=Split)
        split_1.to_json.return_value = '{"name": "some_split_1"}'
        split_name_1 = mocker.PropertyMock()
        split_name_1.return_value = 'some_split_1'
        type(split_1).name = split_name_1
        split_2 = mocker.Mock(spec=Split)
        split_2.to_json.return_value = '{"name": "some_split_2"}'
        split_name_2 = mocker.PropertyMock()
        split_name_2.return_value = 'some_split_2'
        type(split_2).name = split_name_2

        def _from_raw_mock(split_json):
            split_mock = mocker.Mock(spec=Split)
            name = mocker.PropertyMock()
            name.return_value = json.loads(split_json)['name']
            type(split_mock).name = name
            return split_mock
        mocker.patch('splitio.storage.uwsgi.splits.from_raw', new=_from_raw_mock)

        storage.put(split_1)
        storage.put(split_2)

        splits = storage.get_all_splits()
        s1 = next(split for split in splits if split.name == 'some_split_1')
        s2 = next(split for split in splits if split.name == 'some_split_2')
예제 #5
0
 def test_get_set_change_number(self, mocker):
     """Test setting and getting change number."""
     uwsgi = get_uwsgi(True)
     storage = UWSGISegmentStorage(uwsgi)
     assert storage.get_change_number('some_segment') is None
     storage.set_change_number('some_segment', 123)
     assert storage.get_change_number('some_segment') == 123
예제 #6
0
    def test_put_pop_events(self, mocker):
        """Test storing and fetching events."""
        uwsgi = get_uwsgi(True)
        storage = UWSGIEventStorage(uwsgi)
        events = [
            EventWrapper(event=Event('key1', 'user', 'purchase', 10, 123456,
                                     None),
                         size=32768),
            EventWrapper(event=Event('key2', 'user', 'purchase', 10, 123456,
                                     None),
                         size=32768),
            EventWrapper(event=Event('key3', 'user', 'purchase', 10, 123456,
                                     None),
                         size=32768),
            EventWrapper(event=Event('key4', 'user', 'purchase', 10, 123456,
                                     None),
                         size=32768),
        ]

        storage.put(events)
        res = storage.pop_many(10)
        assert res == [
            Event('key1', 'user', 'purchase', 10, 123456, None),
            Event('key2', 'user', 'purchase', 10, 123456, None),
            Event('key3', 'user', 'purchase', 10, 123456, None),
            Event('key4', 'user', 'purchase', 10, 123456, None)
        ]
예제 #7
0
    def test_store_retrieve_segment(self, mocker):
        """Test storing and fetching segments."""
        uwsgi = get_uwsgi(True)
        storage = UWSGISegmentStorage(uwsgi)
        segment = mocker.Mock(spec=Segment)
        segment_keys = mocker.PropertyMock()
        segment_keys.return_value = ['abc']
        type(segment).keys = segment_keys
        segment.to_json = {}
        segment_name = mocker.PropertyMock()
        segment_name.return_value = 'some_segment'
        segment_change_number = mocker.PropertyMock()
        segment_change_number.return_value = 123
        type(segment).name = segment_name
        type(segment).change_number = segment_change_number
        from_raw_mock = mocker.Mock()
        from_raw_mock.return_value = 'ok'
        mocker.patch('splitio.models.segments.from_raw', new=from_raw_mock)

        storage.put(segment)
        assert storage.get('some_segment') == 'ok'
        assert from_raw_mock.mock_calls == [
            mocker.call({
                'till': 123,
                'removed': [],
                'added': [u'abc'],
                'name': 'some_segment'
            })
        ]
        assert storage.get('nonexistant-segment') is None
예제 #8
0
def uwsgi_report_events(user_config):
    """
    Flush events task.

    :param user_config: User-provided configuration.
    :type user_config: dict
    """
    config = _get_config(user_config)
    metadata = get_metadata(config)
    seconds = config.get('eventsRefreshRate', 30)
    storage = UWSGIEventStorage(get_uwsgi())
    task = EventsSyncTask(
        EventsAPI(
            HttpClient(1500, config.get('sdk_url'), config.get('events_url')),
            config['apikey'], metadata),
        storage,
        None,  # Period not needed. Task is being triggered manually.
        config['eventsBulkSize'])
    while True:
        try:
            task._send_events()  #pylint: disable=protected-access
            for _ in xrange(0, seconds):
                if storage.should_flush():
                    storage.acknowledge_flush()
                    break
                time.sleep(1)
        except Exception:  #pylint: disable=broad-except
            _LOGGER.error('Error posting metrics')
            _LOGGER.debug('Error: ', exc_info=True)
예제 #9
0
def uwsgi_report_telemetry(user_config):
    """
    Flush events task.

    :param user_config: User-provided configuration.
    :type user_config: dict
    """
    config = _get_config(user_config)
    metadata = get_metadata(config)
    seconds = config.get('metricsRefreshRate', 30)
    storage = UWSGITelemetryStorage(get_uwsgi())
    task = TelemetrySynchronizationTask(
        TelemetryAPI(
            HttpClient(1500, config.get('sdk_url'), config.get('events_url')),
            config['apikey'], metadata),
        storage,
        None,  # Period not needed. Task is being triggered manually.
    )
    while True:
        try:
            task._flush_telemetry()  #pylint: disable=protected-access
            time.sleep(seconds)
        except Exception:  #pylint: disable=broad-except
            _LOGGER.error('Error posting metrics')
            _LOGGER.debug('Error: ', exc_info=True)
예제 #10
0
def uwsgi_update_splits(user_config):
    """
    Update splits task.

    :param user_config: User-provided configuration.
    :type user_config: dict
    """
    config = _get_config(user_config)
    seconds = config['featuresRefreshRate']
    split_sync_task = SplitSynchronizationTask(
        SplitsAPI(
            HttpClient(1500, config.get('sdk_url'), config.get('events_url')),
            config['apikey']),
        UWSGISplitStorage(get_uwsgi()),
        None,  # Time not needed since the task will be triggered manually.
        None  # Ready flag not needed since it will never be set and consumed.
    )

    while True:
        try:
            split_sync_task._update_splits()  #pylint: disable=protected-access
            time.sleep(seconds)
        except Exception:  #pylint: disable=broad-except
            _LOGGER.error('Error updating splits')
            _LOGGER.debug('Error: ', exc_info=True)
예제 #11
0
    def test_is_valid_traffic_type(self, mocker):
        """Test that traffic type validation works properly."""
        uwsgi = get_uwsgi(True)
        storage = UWSGISplitStorage(uwsgi)
        from_raw_mock = self._get_from_raw_mock(mocker)
        mocker.patch('splitio.models.splits.from_raw', new=from_raw_mock)

        split_1 = from_raw_mock({'name': 'some_split_1', 'trafficTypeName': 'user'})
        storage.put(split_1)
        assert storage.is_valid_traffic_type('user') is True
        assert storage.is_valid_traffic_type('account') is False

        split_2 = from_raw_mock({'name': 'some_split_2', 'trafficTypeName': 'account'})
        storage.put(split_2)
        assert storage.is_valid_traffic_type('user') is True
        assert storage.is_valid_traffic_type('account') is True

        split_3 = from_raw_mock({'name': 'some_split_3', 'trafficTypeName': 'user'})
        storage.put(split_3)
        assert storage.is_valid_traffic_type('user') is True
        assert storage.is_valid_traffic_type('account') is True

        storage.remove('some_split_1')
        assert storage.is_valid_traffic_type('user') is True
        assert storage.is_valid_traffic_type('account') is True

        storage.remove('some_split_2')
        assert storage.is_valid_traffic_type('user') is True
        assert storage.is_valid_traffic_type('account') is False

        storage.remove('some_split_3')
        assert storage.is_valid_traffic_type('user') is False
        assert storage.is_valid_traffic_type('account') is False
예제 #12
0
def uwsgi_report_impressions(user_config):
    """
    Flush impressions task.

    :param user_config: User-provided configuration.
    :type user_config: dict
    """
    config = _get_config(user_config)
    metadata = get_metadata(config)
    seconds = config['impressionsRefreshRate']
    storage = UWSGIImpressionStorage(get_uwsgi())
    impressions_sync = ImpressionSynchronizer(
        ImpressionsAPI(
            HttpClient(1500, config.get('sdk_url'), config.get('events_url')),
            config['apikey'], metadata, config['impressionsMode']), storage,
        config['impressionsBulkSize'])

    while True:
        try:
            impressions_sync.synchronize_impressions()  # pylint: disable=protected-access
            for _ in range(0, seconds):
                if storage.should_flush():
                    storage.acknowledge_flush()
                    break
                time.sleep(1)
        except Exception:  # pylint: disable=broad-except
            _LOGGER.error('Error posting impressions')
            _LOGGER.debug('Error: ', exc_info=True)
예제 #13
0
    def test_set_get_changenumber(self, mocker):
        """Test setting and retrieving changenumber."""
        uwsgi = get_uwsgi(True)
        storage = UWSGISplitStorage(uwsgi)

        assert storage.get_change_number() == None
        storage.set_change_number(123)
        assert storage.get_change_number() == 123
예제 #14
0
 def test_counters(self):
     """Test storing and popping counters."""
     storage = UWSGITelemetryStorage(get_uwsgi(True))
     storage.inc_counter('some_counter')
     storage.inc_counter('some_counter')
     storage.inc_counter('some_counter')
     assert storage.pop_counters() == {'some_counter': 3}
     assert storage.pop_counters() == {}
예제 #15
0
 def test_flush(self):
     """Test requesting, querying and acknowledging a flush."""
     uwsgi = get_uwsgi(True)
     storage = UWSGIImpressionStorage(uwsgi)
     assert storage.should_flush() is False
     storage.request_flush()
     assert storage.should_flush() is True
     storage.acknowledge_flush()
     assert storage.should_flush() is False
예제 #16
0
 def test_latencies(self):
     """Test storing and popping latencies."""
     storage = UWSGITelemetryStorage(get_uwsgi(True))
     storage.inc_latency('some_latency', 2)
     storage.inc_latency('some_latency', 2)
     storage.inc_latency('some_latency', 2)
     assert storage.pop_latencies() == {
         'some_latency': [0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
     }
     assert storage.pop_latencies() == {}
예제 #17
0
 def test_put_pop_impressions(self, mocker):
     """Test storing and fetching impressions."""
     uwsgi = get_uwsgi(True)
     storage = UWSGIImpressionStorage(uwsgi)
     impressions = [
         Impression('key1', 'feature1', 'on', 'some_label', 123456, 'buck1', 321654),
         Impression('key2', 'feature2', 'on', 'some_label', 123456, 'buck1', 321654),
         Impression('key3', 'feature2', 'on', 'some_label', 123456, 'buck1', 321654),
         Impression('key4', 'feature1', 'on', 'some_label', 123456, 'buck1', 321654)
     ]
     storage.put(impressions)
     res = storage.pop_many(10)
     assert res == impressions
예제 #18
0
    def test_get_split_names(self, mocker):
        """Test getting all split names."""
        uwsgi = get_uwsgi(True)
        storage = UWSGISplitStorage(uwsgi)
        from_raw_mock = self._get_from_raw_mock(mocker)
        mocker.patch('splitio.models.splits.from_raw', new=from_raw_mock)

        split_1 = from_raw_mock({'name': 'some_split_1', 'trafficTypeName': 'user'})
        split_2 = from_raw_mock({'name': 'some_split_2', 'trafficTypeName': 'user'})
        storage.put(split_1)
        storage.put(split_2)

        assert set(storage.get_split_names()) == set(['some_split_1', 'some_split_2'])
        storage.remove('some_split_1')
        assert storage.get_split_names() == ['some_split_2']
예제 #19
0
def _build_uwsgi_factory(config):
    """Build and return a split factory with redis-based storage."""
    cfg = DEFAULT_CONFIG.copy()
    cfg.update(config)
    sdk_metadata = util.get_metadata(cfg)
    uwsgi_adapter = get_uwsgi()
    storages = {
        'splits': UWSGISplitStorage(uwsgi_adapter),
        'segments': UWSGISegmentStorage(uwsgi_adapter),
        'impressions': UWSGIImpressionStorage(uwsgi_adapter),
        'events': UWSGIEventStorage(uwsgi_adapter),
        'telemetry': UWSGITelemetryStorage(uwsgi_adapter)
    }
    return SplitFactory(storages,
                        cfg['labelsEnabled'],
                        impression_listener=_wrap_impression_listener(
                            cfg['impressionListener'], sdk_metadata))
예제 #20
0
    def test_get_splits(self, mocker):
        """Test retrieving a list of passed splits."""
        uwsgi = get_uwsgi(True)
        storage = UWSGISplitStorage(uwsgi)
        from_raw_mock = self._get_from_raw_mock(mocker)
        mocker.patch('splitio.models.splits.from_raw', new=from_raw_mock)

        split_1 = from_raw_mock({'name': 'some_split_1', 'trafficTypeName': 'user'})
        split_2 = from_raw_mock({'name': 'some_split_2', 'trafficTypeName': 'user'})
        storage.put(split_1)
        storage.put(split_2)

        splits = storage.fetch_many(['some_split_1', 'some_split_2', 'some_split_3'])
        assert len(splits) == 3
        assert splits['some_split_1'].name == 'some_split_1'
        assert splits['some_split_2'].name == 'some_split_2'
        assert 'some_split_3' in splits
예제 #21
0
    def test_get_all_splits(self, mocker):
        """Test fetching all splits."""
        uwsgi = get_uwsgi(True)
        storage = UWSGISplitStorage(uwsgi)
        from_raw_mock = self._get_from_raw_mock(mocker)
        mocker.patch('splitio.models.splits.from_raw', new=from_raw_mock)

        split_1 = from_raw_mock({'name': 'some_split_1', 'trafficTypeName': 'user'})
        split_2 = from_raw_mock({'name': 'some_split_2', 'trafficTypeName': 'user'})
        storage.put(split_1)
        storage.put(split_2)

        splits = storage.get_all_splits()
        s1 = next(split for split in splits if split.name == 'some_split_1')
        s2 = next(split for split in splits if split.name == 'some_split_2')

        assert s1.traffic_type_name == 'user'
        assert s2.traffic_type_name == 'user'
예제 #22
0
def _build_uwsgi_factory(api_key, cfg):
    """Build and return a split factory with redis-based storage."""
    sdk_metadata = util.get_metadata(cfg)
    uwsgi_adapter = get_uwsgi()
    storages = {
        'splits': UWSGISplitStorage(uwsgi_adapter),
        'segments': UWSGISegmentStorage(uwsgi_adapter),
        'impressions': UWSGIImpressionStorage(uwsgi_adapter),
        'events': UWSGIEventStorage(uwsgi_adapter),
        'telemetry': UWSGITelemetryStorage(uwsgi_adapter)
    }
    return SplitFactory(
        api_key,
        storages,
        cfg['labelsEnabled'],
        ImpressionsManager(storages['impressions'].put, cfg['impressionsMode'], True,
                           _wrap_impression_listener(cfg['impressionListener'], sdk_metadata))
    )
예제 #23
0
 def test_get_split_names(self, mocker):
     """Test getting all split names."""
     uwsgi = get_uwsgi(True)
     storage = UWSGISplitStorage(uwsgi)
     split_1 = mocker.Mock(spec=Split)
     split_1.to_json.return_value = '{"name": "split1"}'
     split_name_1 = mocker.PropertyMock()
     split_name_1.return_value = 'some_split_1'
     type(split_1).name = split_name_1
     split_2 = mocker.Mock(spec=Split)
     split_2.to_json.return_value = '{"name": "split2"}'
     split_name_2 = mocker.PropertyMock()
     split_name_2.return_value = 'some_split_2'
     type(split_2).name = split_name_2
     storage.put(split_1)
     storage.put(split_2)
     assert set(storage.get_split_names()) == set(['some_split_1', 'some_split_2'])
     storage.remove('some_split_1')
     assert storage.get_split_names() == ['some_split_2']
예제 #24
0
    def test_kill_locally(self):
        """Test kill local."""
        uwsgi = get_uwsgi(True)
        storage = UWSGISplitStorage(uwsgi)

        split = Split('some_split', 123456789, False, 'some', 'traffic_type',
                      'ACTIVE', 1)
        storage.put(split)
        storage.set_change_number(1)

        storage.kill_locally('test', 'default_treatment', 2)
        assert storage.get('test') is None

        storage.kill_locally('some_split', 'default_treatment', 0)
        assert storage.get('some_split').change_number == 1
        assert storage.get('some_split').killed is False
        assert storage.get('some_split').default_treatment == 'some'

        storage.kill_locally('some_split', 'default_treatment', 3)
        assert storage.get('some_split').change_number == 3
예제 #25
0
    def test_store_retrieve_split(self, mocker):
        """Test storing and retrieving splits."""
        uwsgi = get_uwsgi(True)
        storage = UWSGISplitStorage(uwsgi)
        from_raw_mock = self._get_from_raw_mock(mocker)
        mocker.patch('splitio.models.splits.from_raw', new=from_raw_mock)

        raw_split = {'name': 'some_split', 'trafficTypeName': 'user'}
        split = from_raw_mock(raw_split)

        from_raw_mock.reset_mock()  # clear mock calls so they don't interfere with the testing itself.
        storage.put(split)

        retrieved = storage.get('some_split')

        assert retrieved.name == split.name and retrieved.traffic_type_name == split.traffic_type_name
        assert from_raw_mock.mock_calls == [mocker.call(raw_split)]
        assert split.to_json.mock_calls == [mocker.call()]

        assert storage.get('nonexistant_split') is None

        storage.remove('some_split')
        assert storage.get('some_split') == None
예제 #26
0
    def test_segment_contains(self, mocker):
        """Test that segment contains works properly."""
        uwsgi = get_uwsgi(True)
        storage = UWSGISegmentStorage(uwsgi)

        from_raw_mock = mocker.Mock()
        from_raw_mock.return_value = Segment('some_segment', ['abc'], 123)
        mocker.patch('splitio.models.segments.from_raw', new=from_raw_mock)
        segment = mocker.Mock(spec=Segment)
        segment_keys = mocker.PropertyMock()
        segment_keys.return_value = ['abc']
        type(segment).keys = segment_keys
        segment.to_json = {}
        segment_name = mocker.PropertyMock()
        segment_name.return_value = 'some_segment'
        segment_change_number = mocker.PropertyMock()
        segment_change_number.return_value = 123
        type(segment).name = segment_name
        type(segment).change_number = segment_change_number
        storage.put(segment)

        assert storage.segment_contains('some_segment', 'abc')
        assert not storage.segment_contains('some_segment', 'qwe')
예제 #27
0
def uwsgi_update_splits(user_config):
    """
    Update splits task.

    :param user_config: User-provided configuration.
    :type user_config: dict
    """
    config = _get_config(user_config)
    seconds = config['featuresRefreshRate']
    split_sync = SplitSynchronizer(
        SplitsAPI(
            HttpClient(1500, config.get('sdk_url'), config.get('events_url')),
            config['apikey']),
        UWSGISplitStorage(get_uwsgi()),
    )

    while True:
        try:
            split_sync.synchronize_splits()  # pylint: disable=protected-access
            time.sleep(seconds)
        except Exception:  # pylint: disable=broad-except
            _LOGGER.error('Error updating splits')
            _LOGGER.debug('Error: ', exc_info=True)
예제 #28
0
    def test_store_retrieve_split(self, mocker):
        """Test storing and retrieving splits."""
        uwsgi = get_uwsgi(True)
        storage = UWSGISplitStorage(uwsgi)
        split = mocker.Mock(spec=Split)
        split.to_json.return_value = '{}'
        split_name = mocker.PropertyMock()
        split_name.return_value = 'some_split'
        type(split).name = split_name
        storage.put(split)

        from_raw_mock = mocker.Mock()
        from_raw_mock.return_value = 'ok'
        mocker.patch('splitio.models.splits.from_raw', new=from_raw_mock)
        retrieved = storage.get('some_split')

        assert retrieved == 'ok'
        assert from_raw_mock.mock_calls == [mocker.call('{}')]
        assert split.to_json.mock_calls == [mocker.call()]

        assert storage.get('nonexistant_split') is None

        storage.remove('some_split')
        assert storage.get('some_split') == None