Example #1
0
class TelemetrySynchronizationTask(BaseSynchronizationTask):
    """Split Synchronization task class."""
    def __init__(self, synchronize_telemetry, period):
        """
        Class constructor.

        :param synchronize_telemetry: handler.
        :type synchronize_telemetry: splitio.api.telemetry.TelemetryAPI
        :param period: Period of task
        :type period: int

        """
        self._period = period
        self._task = AsyncTask(synchronize_telemetry, period)

    def start(self):
        """Start the task."""
        self._task.start()

    def stop(self, event=None):
        """Stop the task. Accept an optional event to set when the task has finished."""
        self._task.stop(event)

    def is_running(self):
        """
        Return whether the task is running.

        :return: True if the task is running. False otherwise.
        :rtype bool
        """
        return self._task.running()
    def __init__(self, synchronize_counters):
        """
        Class constructor.

        :param synchronize_counters: Handler
        :type synchronize_counters: func

        """
        self._task = AsyncTask(synchronize_counters, self._PERIOD, on_stop=synchronize_counters)
Example #3
0
    def __init__(self, synchronize_events, period):
        """
        Class constructor.

        :param synchronize_events: Events Api object to send data to the backend
        :type synchronize_events: splitio.api.events.EventsAPI
        :param period: How many seconds to wait between subsequent event pushes to the BE.
        :type period: int

        """
        self._period = period
        self._task = AsyncTask(synchronize_events, self._period, on_stop=synchronize_events)
Example #4
0
    def __init__(self, synchronize_telemetry, period):
        """
        Class constructor.

        :param synchronize_telemetry: handler.
        :type synchronize_telemetry: splitio.api.telemetry.TelemetryAPI
        :param period: Period of task
        :type period: int

        """
        self._period = period
        self._task = AsyncTask(synchronize_telemetry, period)
    def __init__(self, synchronize_impressions, period):
        """
        Class constructor.

        :param synchronize_impressions: sender
        :type synchronize_impressions: func
        :param period: How many seconds to wait between subsequent impressions pushes to the BE.
        :type period: int

        """
        self._period = period
        self._task = AsyncTask(synchronize_impressions, self._period,
                               on_stop=synchronize_impressions)
Example #6
0
    def __init__(self, api, storage, period):
        """
        Class constructor.

        :param api: Telemetry API Client.
        :type api: splitio.api.telemetry.TelemetryAPI
        :param storage: Telemetry Storage.
        :type storage: splitio.storage.InMemoryTelemetryStorage
        """
        self._logger = logging.getLogger(self.__class__.__name__)
        self._api = api
        self._period = period
        self._storage = storage
        self._task = AsyncTask(self._flush_telemetry, period)
Example #7
0
    def __init__(self, split_api, split_storage, period, ready_flag):
        """
        Class constructor.

        :param split_api: Split API Client.
        :type split_api: splitio.api.splits.SplitsAPI
        :param split_storage: Split Storage.
        :type split_storage: splitio.storage.InMemorySplitStorage
        :param ready_flag: Flag to set when splits initial sync is complete.
        :type ready_flag: threading.Event
        """
        self._logger = logging.getLogger(self.__class__.__name__)
        self._api = split_api
        self._ready_flag = ready_flag
        self._period = period
        self._split_storage = split_storage
        self._task = AsyncTask(self._update_splits, period, self._on_start)
class ImpressionsCountSyncTask(BaseSynchronizationTask):
    """Impressions synchronization task uses an asynctask.AsyncTask to send impressions."""

    _PERIOD = 1800  # 30 * 60 # 30 minutes

    def __init__(self, synchronize_counters):
        """
        Class constructor.

        :param synchronize_counters: Handler
        :type synchronize_counters: func

        """
        self._task = AsyncTask(synchronize_counters, self._PERIOD, on_stop=synchronize_counters)

    def start(self):
        """Start executing the impressions synchronization task."""
        self._task.start()

    def stop(self, event=None):
        """Stop executing the impressions synchronization task."""
        self._task.stop(event)

    def is_running(self):
        """
        Return whether the task is running or not.

        :return: True if the task is running. False otherwise.
        :rtype: bool
        """
        return self._task.running()

    def flush(self):
        """Flush impressions in storage."""
        self._task.force_execution()
Example #9
0
    def __init__(self, events_api, storage, period, bulk_size):
        """
        Class constructor.

        :param events_api: Events Api object to send data to the backend
        :type events_api: splitio.api.events.EventsAPI
        :param storage: Events Storage
        :type storage: splitio.storage.EventStorage
        :param period: How many seconds to wait between subsequent event pushes to the BE.
        :type period: int
        :param bulk_size: How many events to send per push.
        :type bulk_size: int
        """
        self._logger = logging.getLogger(self.__class__.__name__)
        self._events_api = events_api
        self._storage = storage
        self._period = period
        self._failed = queue.Queue()
        self._bulk_size = bulk_size
        self._task = AsyncTask(self._send_events,
                               self._period,
                               on_stop=self._send_events)
class ImpressionsSyncTask(BaseSynchronizationTask):
    """Impressions synchronization task uses an asynctask.AsyncTask to send impressions."""

    def __init__(self, synchronize_impressions, period):
        """
        Class constructor.

        :param synchronize_impressions: sender
        :type synchronize_impressions: func
        :param period: How many seconds to wait between subsequent impressions pushes to the BE.
        :type period: int

        """
        self._period = period
        self._task = AsyncTask(synchronize_impressions, self._period,
                               on_stop=synchronize_impressions)

    def start(self):
        """Start executing the impressions synchronization task."""
        self._task.start()

    def stop(self, event=None):
        """Stop executing the impressions synchronization task."""
        self._task.stop(event)

    def is_running(self):
        """
        Return whether the task is running or not.

        :return: True if the task is running. False otherwise.
        :rtype: bool
        """
        return self._task.running()

    def flush(self):
        """Flush impressions in storage."""
        _LOGGER.debug('Forcing flush execution for impressions')
        self._task.force_execution()
Example #11
0
class EventsSyncTask(BaseSynchronizationTask):
    """Events synchronization task uses an asynctask.AsyncTask to send events."""
    def __init__(self, synchronize_events, period):
        """
        Class constructor.

        :param synchronize_events: Events Api object to send data to the backend
        :type synchronize_events: splitio.api.events.EventsAPI
        :param period: How many seconds to wait between subsequent event pushes to the BE.
        :type period: int

        """
        self._period = period
        self._task = AsyncTask(synchronize_events,
                               self._period,
                               on_stop=synchronize_events)

    def start(self):
        """Start executing the events synchronization task."""
        self._task.start()

    def stop(self, event=None):
        """Stop executing the events synchronization task."""
        self._task.stop(event)

    def flush(self):
        """Flush events in storage."""
        _LOGGER.debug('Forcing flush execution for events')
        self._task.force_execution()

    def is_running(self):
        """
        Return whether the task is running or not.

        :return: True if the task is running. False otherwise.
        :rtype: bool
        """
        return self._task.running()
Example #12
0
class TelemetrySynchronizationTask(BaseSynchronizationTask):
    """Split Synchronization task class."""

    def __init__(self, api, storage, period):
        """
        Class constructor.

        :param api: Telemetry API Client.
        :type api: splitio.api.telemetry.TelemetryAPI
        :param storage: Telemetry Storage.
        :type storage: splitio.storage.InMemoryTelemetryStorage
        """
        self._logger = logging.getLogger(self.__class__.__name__)
        self._api = api
        self._period = period
        self._storage = storage
        self._task = AsyncTask(self._flush_telemetry, period)

    def _flush_telemetry(self):
        """
        Send latencies, counters and gauges to split BE.

        :return: True if synchronization is complete.
        :rtype: bool
        """
        try:
            latencies = self._storage.pop_latencies()
            if latencies:
                self._api.flush_latencies(latencies)
        except APIException:
            self._logger.error('Failed send telemetry/latencies to split BE.')

        try:
            counters = self._storage.pop_counters()
            if counters:
                self._api.flush_counters(counters)
        except APIException:
            self._logger.error('Failed send telemetry/counters to split BE.')

        try:
            gauges = self._storage.pop_gauges()
            if gauges:
                self._api.flush_gauges(gauges)
        except APIException:
            self._logger.error('Failed send telemetry/gauges to split BE.')

    def start(self):
        """Start the task."""
        self._task.start()

    def stop(self, event=None):
        """Stop the task. Accept an optional event to set when the task has finished."""
        self._task.stop(event)

    def is_running(self):
        """
        Return whether the task is running.

        :return: True if the task is running. False otherwise.
        :rtype bool
        """
        return self._task.running()
Example #13
0
class SplitSynchronizationTask(BaseSynchronizationTask):
    """Split Synchronization task class."""
    def __init__(self, split_api, split_storage, period, ready_flag):
        """
        Class constructor.

        :param split_api: Split API Client.
        :type split_api: splitio.api.splits.SplitsAPI
        :param split_storage: Split Storage.
        :type split_storage: splitio.storage.InMemorySplitStorage
        :param ready_flag: Flag to set when splits initial sync is complete.
        :type ready_flag: threading.Event
        """
        self._logger = logging.getLogger(self.__class__.__name__)
        self._api = split_api
        self._ready_flag = ready_flag
        self._period = period
        self._split_storage = split_storage
        self._task = AsyncTask(self._update_splits, period, self._on_start)

    def _update_splits(self):
        """
        Hit endpoint, update storage and return True if sync is complete.

        :return: True if synchronization is complete.
        :rtype: bool
        """
        till = self._split_storage.get_change_number()
        if till is None:
            till = -1

        try:
            split_changes = self._api.fetch_splits(till)
        except APIException:
            self._logger.error('Failed to fetch split from servers')
            return False

        for split in split_changes.get('splits', []):
            if split['status'] == splits.Status.ACTIVE.value:
                self._split_storage.put(splits.from_raw(split))
            else:
                self._split_storage.remove(split['name'])

        self._split_storage.set_change_number(split_changes['till'])
        return split_changes['till'] == split_changes['since']

    def _on_start(self):
        """Wait until splits are in sync and set the flag to true."""
        while True:
            ready = self._update_splits()
            if ready:
                break

        self._ready_flag.set()
        return True

    def start(self):
        """Start the task."""
        self._task.start()

    def stop(self, event=None):
        """Stop the task. Accept an optional event to set when the task has finished."""
        self._task.stop(event)

    def is_running(self):
        """
        Return whether the task is running.

        :return: True if the task is running. False otherwise.
        :rtype bool
        """
        return self._task.running()
Example #14
0
class EventsSyncTask(BaseSynchronizationTask):
    """Events synchronization task uses an asynctask.AsyncTask to send events."""
    def __init__(self, events_api, storage, period, bulk_size):
        """
        Class constructor.

        :param events_api: Events Api object to send data to the backend
        :type events_api: splitio.api.events.EventsAPI
        :param storage: Events Storage
        :type storage: splitio.storage.EventStorage
        :param period: How many seconds to wait between subsequent event pushes to the BE.
        :type period: int
        :param bulk_size: How many events to send per push.
        :type bulk_size: int
        """
        self._logger = logging.getLogger(self.__class__.__name__)
        self._events_api = events_api
        self._storage = storage
        self._period = period
        self._failed = queue.Queue()
        self._bulk_size = bulk_size
        self._task = AsyncTask(self._send_events,
                               self._period,
                               on_stop=self._send_events)

    def _get_failed(self):
        """Return up to <BULK_SIZE> events stored in the failed eventes queue."""
        events = []
        count = 0
        while count < self._bulk_size:
            try:
                events.append(self._failed.get(False))
                count += 1
            except queue.Empty:
                # If no more items in queue, break the loop
                break
        return events

    def _add_to_failed_queue(self, events):
        """
        Add events that were about to be sent to a secondary queue for failed sends.

        :param events: List of events that failed to be pushed.
        :type events: list
        """
        for event in events:
            self._failed.put(event, False)

    def _send_events(self):
        """Send events from both the failed and new queues."""
        to_send = self._get_failed()
        if len(to_send) < self._bulk_size:
            # If the amount of previously failed items is less than the bulk
            # size, try to complete with new events from storage
            to_send.extend(
                self._storage.pop_many(self._bulk_size - len(to_send)))

        if not to_send:
            return

        try:
            self._events_api.flush_events(to_send)
        except APIException as exc:
            self._logger.error(
                'Exception raised while reporting events: %s -- %d',
                exc.message, exc.status_code)
            self._add_to_failed_queue(to_send)

    def start(self):
        """Start executing the events synchronization task."""
        self._task.start()

    def stop(self, event=None):
        """Stop executing the events synchronization task."""
        self._task.stop(event)

    def flush(self):
        """Flush events in storage."""
        self._task.force_execution()

    def is_running(self):
        """
        Return whether the task is running or not.

        :return: True if the task is running. False otherwise.
        :rtype: bool
        """
        return self._task.running()