|
@@ -190,6 +190,7 @@ class GroupSnoozeTest(
|
|
|
|
|
|
|
|
|
@apply_feature_flag_on_cls("organizations:groupsnooze-cached-counts")
|
|
|
+@apply_feature_flag_on_cls("organizations:groupsnooze-cached-rates")
|
|
|
class GroupSnoozeWCacheTest(GroupSnoozeTest):
|
|
|
"""
|
|
|
Test the cached version of the snooze.
|
|
@@ -367,3 +368,82 @@ class GroupSnoozeWCacheTest(GroupSnoozeTest):
|
|
|
assert not snooze.is_valid(test_rates=True)
|
|
|
assert mocked_count_users_seen.call_count == 3
|
|
|
assert cache_spy.set.called_with(cache_key, 100, 300)
|
|
|
+
|
|
|
+ def test_test_frequency_rates_w_cache(self):
|
|
|
+ snooze = GroupSnooze.objects.create(group=self.group, count=100, window=60)
|
|
|
+
|
|
|
+ cache_key = f"groupsnooze:v1:{snooze.id}:test_frequency_rate:events_seen_counter"
|
|
|
+
|
|
|
+ with (
|
|
|
+ mock.patch("sentry.models.groupsnooze.tsdb.backend.get_sums") as mocked_get_sums,
|
|
|
+ mock.patch.object(
|
|
|
+ sentry.models.groupsnooze, "cache", wraps=sentry.models.groupsnooze.cache # type: ignore[attr-defined]
|
|
|
+ ) as cache_spy,
|
|
|
+ ):
|
|
|
+ mocked_get_sums.side_effect = [{snooze.group_id: c} for c in [95, 98, 100]]
|
|
|
+
|
|
|
+ cache_spy.set = mock.Mock(side_effect=cache_spy.set)
|
|
|
+ cache_spy.incr = mock.Mock(side_effect=cache_spy.incr)
|
|
|
+
|
|
|
+ assert snooze.is_valid(test_rates=True)
|
|
|
+ assert mocked_get_sums.call_count == 1
|
|
|
+ assert cache_spy.set.called_with(cache_key, 95, 3600)
|
|
|
+
|
|
|
+ assert snooze.is_valid(test_rates=True)
|
|
|
+ assert mocked_get_sums.call_count == 1
|
|
|
+ assert cache_spy.incr.called_with(cache_key)
|
|
|
+ assert cache_spy.get(cache_key) == 96
|
|
|
+
|
|
|
+ assert snooze.is_valid(test_rates=True)
|
|
|
+ assert cache_spy.get(cache_key) == 97
|
|
|
+ assert snooze.is_valid(test_rates=True)
|
|
|
+ assert cache_spy.get(cache_key) == 98
|
|
|
+ assert snooze.is_valid(test_rates=True)
|
|
|
+ assert cache_spy.get(cache_key) == 99
|
|
|
+
|
|
|
+ # cache counter reaches 100, but gets 98 from get_distinct_counts_totals
|
|
|
+
|
|
|
+ assert snooze.is_valid(test_rates=True)
|
|
|
+ assert mocked_get_sums.call_count == 2
|
|
|
+ assert cache_spy.set.called_with(cache_key, 98, 3600)
|
|
|
+ assert cache_spy.get(cache_key) == 98
|
|
|
+
|
|
|
+ assert snooze.is_valid(test_rates=True)
|
|
|
+ assert cache_spy.get(cache_key) == 99
|
|
|
+ # with this call counter reaches 100, gets 100 from get_distinct_counts_totals, so is_valid returns False
|
|
|
+ assert not snooze.is_valid(test_rates=True)
|
|
|
+ assert mocked_get_sums.call_count == 3
|
|
|
+
|
|
|
+ def test_test_frequency_rates_w_cache_expired(self):
|
|
|
+ snooze = GroupSnooze.objects.create(group=self.group, count=100, window=60)
|
|
|
+
|
|
|
+ cache_key = f"groupsnooze:v1:{snooze.id}:test_frequency_rate:events_seen_counter"
|
|
|
+
|
|
|
+ with (
|
|
|
+ mock.patch("sentry.models.groupsnooze.tsdb.backend.get_sums") as mocked_get_sums,
|
|
|
+ mock.patch.object(
|
|
|
+ sentry.models.groupsnooze, "cache", wraps=sentry.models.groupsnooze.cache # type: ignore[attr-defined]
|
|
|
+ ) as cache_spy,
|
|
|
+ ):
|
|
|
+ mocked_get_sums.side_effect = [{snooze.group_id: c} for c in [98, 99, 100]]
|
|
|
+
|
|
|
+ cache_spy.set = mock.Mock(side_effect=cache_spy.set)
|
|
|
+ cache_spy.incr = mock.Mock(side_effect=cache_spy.incr)
|
|
|
+
|
|
|
+ assert snooze.is_valid(test_rates=True)
|
|
|
+ assert mocked_get_sums.call_count == 1
|
|
|
+ assert cache_spy.set.called_with(cache_key, 98, 3600)
|
|
|
+
|
|
|
+ # simulate cache expiration
|
|
|
+ cache_spy.delete(cache_key)
|
|
|
+
|
|
|
+ assert snooze.is_valid(test_rates=True)
|
|
|
+ assert mocked_get_sums.call_count == 2
|
|
|
+ assert cache_spy.set.called_with(cache_key, 99, 3600)
|
|
|
+
|
|
|
+ # simulate cache expiration
|
|
|
+ cache_spy.delete(cache_key)
|
|
|
+
|
|
|
+ assert not snooze.is_valid(test_rates=True)
|
|
|
+ assert mocked_get_sums.call_count == 3
|
|
|
+ assert cache_spy.set.called_with(cache_key, 100, 3600)
|