mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-11-02 03:40:31 +03:00
write held notice repeats before the analytics baseline reset
Repeats of batched kinds like failed_login wait in memory until the stats emitter flushes them, so a baseline reset taken while some were held left them out, and the next flush counted those pre-opt-in repeats as post-consent. The reset now writes held repeats to the notice history under the same lock before copying the counts.
This commit is contained in:
+29
-18
@@ -132,24 +132,7 @@ class NoticeRegistry:
|
||||
def flush(self) -> None:
|
||||
"""Write the repeats that batch_repeats kinds held back."""
|
||||
with self._lock:
|
||||
held, self._held = self._held, {}
|
||||
written = False
|
||||
|
||||
for row_id, repeats in held.items():
|
||||
row = Notice.get_or_none(Notice.id == row_id)
|
||||
|
||||
# resolved while its repeats waited
|
||||
if row is None:
|
||||
continue
|
||||
|
||||
self._write_repeats(
|
||||
row,
|
||||
repeats.kind,
|
||||
repeats.count,
|
||||
repeats.last_seen,
|
||||
repeats.params,
|
||||
)
|
||||
written = True
|
||||
written = self._write_held()
|
||||
|
||||
if written:
|
||||
self._notify()
|
||||
@@ -388,12 +371,40 @@ class NoticeRegistry:
|
||||
def reset_analytics_baseline(self) -> None:
|
||||
"""Count analytics notices from now on, for a new analytics install ID."""
|
||||
with self._lock:
|
||||
# held repeats were raised before the reset, so they join the baseline
|
||||
written = self._write_held()
|
||||
NoticeStats.update(
|
||||
reported_occurrences=NoticeStats.occurrences,
|
||||
reported_acknowledgements=NoticeStats.acknowledgements,
|
||||
reported_mutes=NoticeStats.mutes,
|
||||
).execute()
|
||||
|
||||
if written:
|
||||
self._notify()
|
||||
|
||||
def _write_held(self) -> bool:
|
||||
# called with the lock held
|
||||
held, self._held = self._held, {}
|
||||
written = False
|
||||
|
||||
for row_id, repeats in held.items():
|
||||
row = Notice.get_or_none(Notice.id == row_id)
|
||||
|
||||
# resolved while its repeats waited
|
||||
if row is None:
|
||||
continue
|
||||
|
||||
self._write_repeats(
|
||||
row,
|
||||
repeats.kind,
|
||||
repeats.count,
|
||||
repeats.last_seen,
|
||||
repeats.params,
|
||||
)
|
||||
written = True
|
||||
|
||||
return written
|
||||
|
||||
def _write_repeats(
|
||||
self,
|
||||
row: Notice,
|
||||
|
||||
@@ -379,6 +379,18 @@ class TestAnalyticsBaseline(RegistryTestCase):
|
||||
)
|
||||
self.assertEqual(rows["skipped_detections"]["reported_occurrences"], 0)
|
||||
|
||||
@patch.dict(NOTICE_KINDS, TEST_KINDS)
|
||||
def test_reset_puts_held_repeats_in_the_baseline(self):
|
||||
for _ in range(3):
|
||||
self.registry.raise_notice("batched")
|
||||
|
||||
self.registry.reset_analytics_baseline()
|
||||
self.registry.flush()
|
||||
|
||||
[row] = self.registry.stats()
|
||||
self.assertEqual((row["occurrences"], row["reported_occurrences"]), (3, 3))
|
||||
self.assertEqual(self.registry.active()[0]["count"], 3)
|
||||
|
||||
|
||||
class TestApply(RegistryTestCase):
|
||||
def test_each_action_reaches_its_method(self):
|
||||
|
||||
Reference in New Issue
Block a user