From d94132a598cb8ce3c930cb3155f1bad8208512c9 Mon Sep 17 00:00:00 2001 From: Cohen Karnell <7363269+ckarnell@users.noreply.github.com> Date: Sat, 15 Aug 2026 15:53:16 -0400 Subject: [PATCH] fix(BufferedConsumer): persist drained buffer per batch so a partial flush does not resend delivered events --- mixpanel/__init__.py | 2 +- test_mixpanel.py | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/mixpanel/__init__.py b/mixpanel/__init__.py index 4cc23f5..2712d36 100644 --- a/mixpanel/__init__.py +++ b/mixpanel/__init__.py @@ -969,4 +969,4 @@ def _flush_endpoint(self, endpoint): mp_e.endpoint = endpoint raise mp_e from orig_e buf = buf[self._max_size :] - self._buffers[endpoint] = buf + self._buffers[endpoint] = buf diff --git a/test_mixpanel.py b/test_mixpanel.py index 4cffaae..cbad72d 100644 --- a/test_mixpanel.py +++ b/test_mixpanel.py @@ -843,6 +843,30 @@ def test_useful_reraise_in_flush_endpoint(self): assert excinfo.value.message == f"[{broken_json}]" assert excinfo.value.endpoint == "events" + def test_partial_flush_does_not_resend_delivered_batches(self): + """A batch the server accepted must not be re-sent when a later one fails.""" + + class FlakyConsumer: + def __init__(self): + self.log = [] + self.calls = 0 + + def send(self, endpoint, event, api_key=None): + self.calls += 1 + if self.calls == 2: + raise mixpanel.MixpanelException("network error") + self.log.append(json.loads(event)) + + consumer = mixpanel.BufferedConsumer(2) + consumer._consumer = FlakyConsumer() + consumer._buffers["events"] = ['"a"', '"b"', '"c"', '"d"'] + + with pytest.raises(mixpanel.MixpanelException): + consumer.flush() + + assert consumer._consumer.log == [["a", "b"]] + assert consumer._buffers["events"] == ['"c"', '"d"'] + def test_send_remembers_api_key(self): self.consumer.send("imports", '"Event"', api_key="MY_API_KEY") assert len(self.log) == 0