def test_synchronize_splits_error(self, mocker):
        """Test that if fetching splits fails at some_point, the task will continue running."""
        storage = mocker.Mock(spec=SplitStorage)
        api = mocker.Mock()

        def run(x):
            raise APIException("something broke")

        run._calls = 0
        api.fetch_splits.side_effect = run
        storage.get_change_number.return_value = -1

        split_synchronizer = SplitSynchronizer(api, storage)

        with pytest.raises(APIException):
            split_synchronizer.synchronize_splits(1)
    def test_not_called_on_till(self, mocker):
        """Test that sync is not called when till is less than previous changenumber"""
        storage = mocker.Mock(spec=SplitStorage)

        def change_number_mock():
            return 2

        storage.get_change_number.side_effect = change_number_mock

        def get_changes(*args, **kwargs):
            get_changes.called += 1
            return None

        get_changes.called = 0

        api = mocker.Mock()
        api.fetch_splits.side_effect = get_changes

        split_synchronizer = SplitSynchronizer(api, storage)
        split_synchronizer.synchronize_splits(1)

        assert get_changes.called == 0
Beispiel #3
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)
Beispiel #4
0
    def test_synchronize_splits(self, mocker):
        """Test split sync."""
        storage = mocker.Mock(spec=SplitStorage)

        def change_number_mock():
            change_number_mock._calls += 1
            if change_number_mock._calls == 1:
                return -1
            return 123

        change_number_mock._calls = 0
        storage.get_change_number.side_effect = change_number_mock
        storage.get_segment_names.return_value = []

        api = mocker.Mock()
        splits = [{
            'changeNumber':
            123,
            'trafficTypeName':
            'user',
            'name':
            'some_name',
            'trafficAllocation':
            100,
            'trafficAllocationSeed':
            123456,
            'seed':
            321654,
            'status':
            'ACTIVE',
            'killed':
            False,
            'defaultTreatment':
            'off',
            'algo':
            2,
            'conditions': [{
                'partitions': [{
                    'treatment': 'on',
                    'size': 50
                }, {
                    'treatment': 'off',
                    'size': 50
                }],
                'contitionType':
                'WHITELIST',
                'label':
                'some_label',
                'matcherGroup': {
                    'matchers': [{
                        'matcherType': 'WHITELIST',
                        'whitelistMatcherData': {
                            'whitelist': ['k1', 'k2', 'k3']
                        },
                        'negate': False,
                    }],
                    'combiner':
                    'AND'
                }
            }]
        }]

        def get_changes(*args, **kwargs):
            get_changes.called += 1

            if get_changes.called == 1:
                return {'splits': splits, 'since': -1, 'till': 123}
            else:
                return {'splits': [], 'since': 123, 'till': 123}

        get_changes.called = 0
        api.fetch_splits.side_effect = get_changes

        from splitio.sync.split import SplitSynchronizer
        split_synchronizer = SplitSynchronizer(api, storage)
        split_synchronizer.synchronize_splits()

        assert mocker.call(-1,
                           FetchOptions(True)) in api.fetch_splits.mock_calls
        assert mocker.call(123,
                           FetchOptions(True)) in api.fetch_splits.mock_calls

        inserted_split = storage.put.mock_calls[0][1][0]
        assert isinstance(inserted_split, Split)
        assert inserted_split.name == 'some_name'
Beispiel #5
0
    def test_synchronize_splits_cdn(self, mocker):
        """Test split sync with bypassing cdn."""
        mocker.patch('splitio.sync.split._ON_DEMAND_FETCH_BACKOFF_MAX_RETRIES',
                     new=3)
        from splitio.sync.split import SplitSynchronizer

        storage = mocker.Mock(spec=SplitStorage)

        def change_number_mock():
            change_number_mock._calls += 1
            if change_number_mock._calls == 1:
                return -1
            elif change_number_mock._calls >= 2 and change_number_mock._calls <= 3:
                return 123
            elif change_number_mock._calls <= 7:
                return 1234
            return 12345  # Return proper cn for CDN Bypass

        change_number_mock._calls = 0
        storage.get_change_number.side_effect = change_number_mock
        storage.get_segment_names.return_value = []

        api = mocker.Mock()
        splits = [{
            'changeNumber':
            123,
            'trafficTypeName':
            'user',
            'name':
            'some_name',
            'trafficAllocation':
            100,
            'trafficAllocationSeed':
            123456,
            'seed':
            321654,
            'status':
            'ACTIVE',
            'killed':
            False,
            'defaultTreatment':
            'off',
            'algo':
            2,
            'conditions': [{
                'partitions': [{
                    'treatment': 'on',
                    'size': 50
                }, {
                    'treatment': 'off',
                    'size': 50
                }],
                'contitionType':
                'WHITELIST',
                'label':
                'some_label',
                'matcherGroup': {
                    'matchers': [{
                        'matcherType': 'WHITELIST',
                        'whitelistMatcherData': {
                            'whitelist': ['k1', 'k2', 'k3']
                        },
                        'negate': False,
                    }],
                    'combiner':
                    'AND'
                }
            }]
        }]

        def get_changes(*args, **kwargs):
            get_changes.called += 1
            if get_changes.called == 1:
                return {'splits': splits, 'since': -1, 'till': 123}
            elif get_changes.called == 2:
                return {'splits': [], 'since': 123, 'till': 123}
            elif get_changes.called == 3:
                return {'splits': [], 'since': 123, 'till': 1234}
            elif get_changes.called >= 4 and get_changes.called <= 6:
                return {'splits': [], 'since': 1234, 'till': 1234}
            elif get_changes.called == 7:
                return {'splits': [], 'since': 1234, 'till': 12345}
            return {'splits': [], 'since': 12345, 'till': 12345}

        get_changes.called = 0
        api.fetch_splits.side_effect = get_changes

        split_synchronizer = SplitSynchronizer(api, storage)
        split_synchronizer._backoff = Backoff(1, 1)
        split_synchronizer.synchronize_splits()

        assert mocker.call(-1,
                           FetchOptions(True)) in api.fetch_splits.mock_calls
        assert mocker.call(123,
                           FetchOptions(True)) in api.fetch_splits.mock_calls

        split_synchronizer._backoff = Backoff(1, 0.1)
        split_synchronizer.synchronize_splits(12345)
        assert mocker.call(12345,
                           FetchOptions(True,
                                        1234)) in api.fetch_splits.mock_calls
        assert len(
            api.fetch_splits.mock_calls
        ) == 8  # 2 ok + BACKOFF(2 since==till + 2 re-attempts) + CDN(2 since==till)

        inserted_split = storage.put.mock_calls[0][1][0]
        assert isinstance(inserted_split, Split)
        assert inserted_split.name == 'some_name'