Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 17feea5

Browse files
authored
Fix: Silence invalid_ack_id warnings for receipt modacks (#798)
1 parent bb42c6f commit 17feea5

File tree

2 files changed

+97
-8
lines changed

2 files changed

+97
-8
lines changed

google/cloud/pubsub_v1/subscriber/_protocol/streaming_pull_manager.py

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -989,7 +989,7 @@ def _get_initial_request(
989989
return request
990990

991991
def _send_lease_modacks(
992-
self, ack_ids: Iterable[str], ack_deadline: float
992+
self, ack_ids: Iterable[str], ack_deadline: float, warn_on_invalid=True
993993
) -> List[str]:
994994
exactly_once_enabled = False
995995
with self._exactly_once_enabled_lock:
@@ -1010,10 +1010,14 @@ def _send_lease_modacks(
10101010
assert req.future is not None
10111011
req.future.result()
10121012
except AcknowledgeError as ack_error:
1013-
_LOGGER.warning(
1014-
"AcknowledgeError when lease-modacking a message.",
1015-
exc_info=True,
1016-
)
1013+
if (
1014+
ack_error.error_code != AcknowledgeStatus.INVALID_ACK_ID
1015+
or warn_on_invalid
1016+
):
1017+
_LOGGER.warning(
1018+
"AcknowledgeError when lease-modacking a message.",
1019+
exc_info=True,
1020+
)
10171021
if ack_error.error_code == AcknowledgeStatus.INVALID_ACK_ID:
10181022
expired_ack_ids.append(req.ack_id)
10191023
return expired_ack_ids
@@ -1078,7 +1082,11 @@ def _on_response(self, response: gapic_types.StreamingPullResponse) -> None:
10781082
# modack the messages we received, as this tells the server that we've
10791083
# received them.
10801084
ack_id_gen = (message.ack_id for message in received_messages)
1081-
expired_ack_ids = set(self._send_lease_modacks(ack_id_gen, self.ack_deadline))
1085+
expired_ack_ids = set(
1086+
self._send_lease_modacks(
1087+
ack_id_gen, self.ack_deadline, warn_on_invalid=False
1088+
)
1089+
)
10821090

10831091
with self._pause_resume_lock:
10841092
assert self._scheduler is not None

tests/unit/pubsub_v1/subscriber/test_streaming_pull_manager.py

Lines changed: 83 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1846,7 +1846,7 @@ def test__on_response_disable_exactly_once():
18461846
assert manager._stream_ack_deadline == 60
18471847

18481848

1849-
def test__on_response_exactly_once_immediate_modacks_fail():
1849+
def test__on_response_exactly_once_immediate_modacks_fail(caplog):
18501850
manager, _, dispatcher, leaser, _, scheduler = make_running_manager()
18511851
manager._callback = mock.sentinel.callback
18521852

@@ -1890,7 +1890,8 @@ def complete_futures_with_error(*args, **kwargs):
18901890

18911891
fake_leaser_add(leaser, init_msg_count=0, assumed_msg_size=10)
18921892

1893-
manager._on_response(response)
1893+
with caplog.at_level(logging.WARNING):
1894+
manager._on_response(response)
18941895

18951896
# The second messages should be scheduled, and not the first.
18961897

@@ -1902,13 +1903,93 @@ def complete_futures_with_error(*args, **kwargs):
19021903
assert call_args[1].message_id == "2"
19031904

19041905
assert manager._messages_on_hold.size == 0
1906+
1907+
expected_warnings = [
1908+
record.message.lower()
1909+
for record in caplog.records
1910+
if "AcknowledgeError when lease-modacking a message." in record.message
1911+
]
1912+
assert len(expected_warnings) == 1
1913+
19051914
# No messages available
19061915
assert manager._messages_on_hold.get() is None
19071916

19081917
# do not add message
19091918
assert manager.load == 0.001
19101919

19111920

1921+
def test__on_response_exactly_once_immediate_modacks_fail_non_invalid(caplog):
1922+
manager, _, dispatcher, leaser, _, scheduler = make_running_manager()
1923+
manager._callback = mock.sentinel.callback
1924+
1925+
def complete_futures_with_error(*args, **kwargs):
1926+
modack_requests = args[0]
1927+
for req in modack_requests:
1928+
if req.ack_id == "fack":
1929+
req.future.set_exception(
1930+
subscriber_exceptions.AcknowledgeError(
1931+
subscriber_exceptions.AcknowledgeStatus.OTHER, None
1932+
)
1933+
)
1934+
else:
1935+
req.future.set_exception(
1936+
subscriber_exceptions.AcknowledgeError(
1937+
subscriber_exceptions.AcknowledgeStatus.SUCCESS, None
1938+
)
1939+
)
1940+
1941+
dispatcher.modify_ack_deadline.side_effect = complete_futures_with_error
1942+
1943+
# Set up the messages.
1944+
response = gapic_types.StreamingPullResponse(
1945+
received_messages=[
1946+
gapic_types.ReceivedMessage(
1947+
ack_id="fack",
1948+
message=gapic_types.PubsubMessage(data=b"foo", message_id="1"),
1949+
),
1950+
gapic_types.ReceivedMessage(
1951+
ack_id="good",
1952+
message=gapic_types.PubsubMessage(data=b"foo", message_id="2"),
1953+
),
1954+
],
1955+
subscription_properties=gapic_types.StreamingPullResponse.SubscriptionProperties(
1956+
exactly_once_delivery_enabled=True
1957+
),
1958+
)
1959+
1960+
# Actually run the method and prove that modack and schedule are called in
1961+
# the expected way.
1962+
1963+
fake_leaser_add(leaser, init_msg_count=0, assumed_msg_size=10)
1964+
1965+
with caplog.at_level(logging.WARNING):
1966+
manager._on_response(response)
1967+
1968+
# The second messages should be scheduled, and not the first.
1969+
1970+
schedule_calls = scheduler.schedule.mock_calls
1971+
assert len(schedule_calls) == 2
1972+
call_args = schedule_calls[0][1]
1973+
assert call_args[0] == mock.sentinel.callback
1974+
assert isinstance(call_args[1], message.Message)
1975+
assert call_args[1].message_id == "1"
1976+
1977+
assert manager._messages_on_hold.size == 0
1978+
1979+
expected_warnings = [
1980+
record.message.lower()
1981+
for record in caplog.records
1982+
if "AcknowledgeError when lease-modacking a message." in record.message
1983+
]
1984+
assert len(expected_warnings) == 2
1985+
1986+
# No messages available
1987+
assert manager._messages_on_hold.get() is None
1988+
1989+
# do not add message
1990+
assert manager.load == 0.002
1991+
1992+
19121993
def test__should_recover_true():
19131994
manager = make_manager()
19141995

0 commit comments

Comments
 (0)