Esempio n. 1
0
    def open(self, callback, on_callback_error):
        """Begin consuming messages.

        Args:
            callback (Callable[None, google.cloud.pubsub_v1.message.Message]):
                A callback that will be called for each message received on the
                stream.
            on_callback_error (Callable[Exception]):
                A callable that will be called if an exception is raised in
                the provided `callback`.
        """
        if self.is_active:
            raise ValueError("This manager is already open.")

        if self._closed:
            raise ValueError("This manager has been closed and can not be re-used.")

        self._callback = functools.partial(
            _wrap_callback_errors, callback, on_callback_error
        )

        # Create the RPC
        stream_ack_deadline_seconds = self.ack_histogram.percentile(99)

        get_initial_request = functools.partial(
            self._get_initial_request, stream_ack_deadline_seconds
        )
        self._rpc = bidi.ResumableBidiRpc(
            start_rpc=self._client.api.streaming_pull,
            initial_request=get_initial_request,
            should_recover=self._should_recover,
            should_terminate=self._should_terminate,
            throttle_reopen=True,
        )
        self._rpc.add_done_callback(self._on_rpc_done)

        _LOGGER.debug(
            "Creating a stream, default ACK deadline set to {} seconds.".format(
                stream_ack_deadline_seconds
            )
        )

        # Create references to threads
        self._dispatcher = dispatcher.Dispatcher(self, self._scheduler.queue)
        self._consumer = bidi.BackgroundConsumer(self._rpc, self._on_response)
        self._leaser = leaser.Leaser(self)
        self._heartbeater = heartbeater.Heartbeater(self)

        # Start the thread to pass the requests.
        self._dispatcher.start()

        # Start consuming messages.
        self._consumer.start()

        # Start the lease maintainer thread.
        self._leaser.start()

        # Start the stream heartbeater thread.
        self._heartbeater.start()
Esempio n. 2
0
def test_heartbeat_once():
    manager = mock.create_autospec(streaming_pull_manager.StreamingPullManager,
                                   instance=True)
    heartbeater_ = heartbeater.Heartbeater(manager)
    make_sleep_mark_event_as_done(heartbeater_)

    heartbeater_.heartbeat()

    manager.heartbeat.assert_called_once()
Esempio n. 3
0
def test_start_already_started(thread):
    manager = mock.create_autospec(streaming_pull_manager.StreamingPullManager,
                                   instance=True)
    heartbeater_ = heartbeater.Heartbeater(manager)
    heartbeater_._thread = mock.sentinel.thread

    with pytest.raises(ValueError):
        heartbeater_.start()

    thread.assert_not_called()
def test_heartbeat_stopped(caplog):
    caplog.set_level(logging.INFO)
    manager = mock.create_autospec(
        streaming_pull_manager.StreamingPullManager, instance=True)

    heartbeater_ = heartbeater.Heartbeater(manager)
    heartbeater_.stop()

    heartbeater_.heartbeat()

    assert 'exiting' in caplog.text
Esempio n. 5
0
def test_stop():
    manager = mock.create_autospec(streaming_pull_manager.StreamingPullManager,
                                   instance=True)
    heartbeater_ = heartbeater.Heartbeater(manager)
    thread = mock.create_autospec(threading.Thread, instance=True)
    heartbeater_._thread = thread

    heartbeater_.stop()

    assert heartbeater_._stop_event.is_set()
    thread.join.assert_called_once()
    assert heartbeater_._thread is None
Esempio n. 6
0
def test_heartbeat_inactive(caplog):
    caplog.set_level(logging.INFO)
    manager = mock.create_autospec(
        streaming_pull_manager.StreamingPullManager, instance=True
    )
    manager.is_active = False

    heartbeater_ = heartbeater.Heartbeater(manager)

    heartbeater_.heartbeat()

    assert "exiting" in caplog.text
Esempio n. 7
0
def test_start(thread):
    manager = mock.create_autospec(streaming_pull_manager.StreamingPullManager,
                                   instance=True)
    heartbeater_ = heartbeater.Heartbeater(manager)

    heartbeater_.start()

    thread.assert_called_once_with(name=heartbeater._HEARTBEAT_WORKER_NAME,
                                   target=heartbeater_.heartbeat)

    thread.return_value.start.assert_called_once()

    assert heartbeater_._thread is not None
Esempio n. 8
0
def test_heartbeat_inactive_manager_inactive_rpc(caplog):
    caplog.set_level(logging.DEBUG)

    manager = mock.create_autospec(streaming_pull_manager.StreamingPullManager,
                                   instance=True)
    manager.is_active = False
    manager.heartbeat.return_value = False  # because of inactive rpc

    heartbeater_ = heartbeater.Heartbeater(manager)
    make_sleep_mark_event_as_done(heartbeater_)

    heartbeater_.heartbeat()

    assert "Sent heartbeat" not in caplog.text
    assert "exiting" in caplog.text
Esempio n. 9
0
    def open(self, callback):
        """Begin consuming messages.

        Args:
            callback (Callable[None, google.cloud.pubsub_v1.message.Messages]):
                A callback that will be called for each message received on the
                stream.
        """
        if self.is_active:
            raise ValueError('This manager is already open.')

        if self._closed:
            raise ValueError(
                'This manager has been closed and can not be re-used.')

        self._callback = functools.partial(_wrap_callback_errors, callback)

        # Create the RPC
        self._rpc = bidi.ResumableBidiRpc(
            start_rpc=self._client.api.streaming_pull,
            initial_request=self._get_initial_request,
            should_recover=self._should_recover)
        self._rpc.add_done_callback(self._on_rpc_done)

        # Create references to threads
        self._dispatcher = dispatcher.Dispatcher(self, self._scheduler.queue)
        self._consumer = bidi.BackgroundConsumer(
            self._rpc, self._on_response)
        self._leaser = leaser.Leaser(self)
        self._heartbeater = heartbeater.Heartbeater(self)

        # Start the thread to pass the requests.
        self._dispatcher.start()

        # Start consuming messages.
        self._consumer.start()

        # Start the lease maintainer thread.
        self._leaser.start()

        # Start the stream heartbeater thread.
        self._heartbeater.start()
Esempio n. 10
0
def test_stop_no_join():
    heartbeater_ = heartbeater.Heartbeater(mock.sentinel.manager)

    heartbeater_.stop()
Esempio n. 11
0
    def open(self, callback, on_callback_error):
        """Begin consuming messages.

        Args:
            callback (Callable[None, google.cloud.pubsub_v1.message.Message]):
                A callback that will be called for each message received on the
                stream.
            on_callback_error (Callable[Exception]):
                A callable that will be called if an exception is raised in
                the provided `callback`.
        """
        if self.is_active:
            raise ValueError("This manager is already open.")

        if self._closed:
            raise ValueError(
                "This manager has been closed and can not be re-used.")

        self._callback = functools.partial(_wrap_callback_errors, callback,
                                           on_callback_error)

        # Create the RPC

        # We must use a fixed value for the ACK deadline, as we cannot read it
        # from the subscription. The latter would require `pubsub.subscriptions.get`
        # permission, which is not granted to the default subscriber role
        # `roles/pubsub.subscriber`.
        # See also https://github.com/googleapis/google-cloud-python/issues/9339
        #
        # When dynamic lease management is enabled for the "on hold" messages,
        # the default stream ACK deadline should again be set based on the
        # historic ACK timing data, i.e. `self.ack_histogram.percentile(99)`.
        stream_ack_deadline_seconds = _DEFAULT_STREAM_ACK_DEADLINE

        get_initial_request = functools.partial(self._get_initial_request,
                                                stream_ack_deadline_seconds)
        self._rpc = bidi.ResumableBidiRpc(
            start_rpc=self._client.api.streaming_pull,
            initial_request=get_initial_request,
            should_recover=self._should_recover,
            should_terminate=self._should_terminate,
            throttle_reopen=True,
        )
        self._rpc.add_done_callback(self._on_rpc_done)

        _LOGGER.debug(
            "Creating a stream, default ACK deadline set to {} seconds.".
            format(stream_ack_deadline_seconds))

        # Create references to threads
        self._dispatcher = dispatcher.Dispatcher(self, self._scheduler.queue)
        self._consumer = bidi.BackgroundConsumer(self._rpc, self._on_response)
        self._leaser = leaser.Leaser(self)
        self._heartbeater = heartbeater.Heartbeater(self)

        # Start the thread to pass the requests.
        self._dispatcher.start()

        # Start consuming messages.
        self._consumer.start()

        # Start the lease maintainer thread.
        self._leaser.start()

        # Start the stream heartbeater thread.
        self._heartbeater.start()