Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(insights): Use lru_cache to reduce queries to instance settings #21938

Merged
merged 11 commits into from
May 30, 2024
2 changes: 1 addition & 1 deletion posthog/api/test/__snapshots__/test_api_docs.ambr
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,8 @@
'/home/runner/work/posthog/posthog/posthog/api/survey.py: Warning [SurveyViewSet]: could not derive type of path parameter "project_id" because model "posthog.models.feedback.survey.Survey" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".',
'Warning: encountered multiple names for the same choice set (HrefMatchingEnum). This may be unwanted even though the generated schema is technically correct. Add an entry to ENUM_NAME_OVERRIDES to fix the naming.',
'Warning: enum naming encountered a non-optimally resolvable collision for fields named "type". The same name has been used for multiple choice sets in multiple components. The collision was resolved with "Type7baEnum". add an entry to ENUM_NAME_OVERRIDES to fix the naming.',
'Warning: enum naming encountered a non-optimally resolvable collision for fields named "level". The same name has been used for multiple choice sets in multiple components. The collision was resolved with "LevelD7eEnum". add an entry to ENUM_NAME_OVERRIDES to fix the naming.',
'Warning: enum naming encountered a non-optimally resolvable collision for fields named "level". The same name has been used for multiple choice sets in multiple components. The collision was resolved with "Level998Enum". add an entry to ENUM_NAME_OVERRIDES to fix the naming.',
'Warning: enum naming encountered a non-optimally resolvable collision for fields named "level". The same name has been used for multiple choice sets in multiple components. The collision was resolved with "LevelD7eEnum". add an entry to ENUM_NAME_OVERRIDES to fix the naming.',
'Warning: encountered multiple names for the same choice set (RestrictionLevelEnum). This may be unwanted even though the generated schema is technically correct. Add an entry to ENUM_NAME_OVERRIDES to fix the naming.',
'Warning: encountered multiple names for the same choice set (EffectivePrivilegeLevelEnum). This may be unwanted even though the generated schema is technically correct. Add an entry to ENUM_NAME_OVERRIDES to fix the naming.',
'Warning: encountered multiple names for the same choice set (MembershipLevelEnum). This may be unwanted even though the generated schema is technically correct. Add an entry to ENUM_NAME_OVERRIDES to fix the naming.',
Expand Down
8 changes: 4 additions & 4 deletions posthog/api/test/test_event.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,8 @@ def test_filter_events_by_event_name(self):
flush_persons_and_events()

# Django session, PostHog user, PostHog team, PostHog org membership,
# 4x instance setting check, person and distinct id
with self.assertNumQueries(10):
# instance setting check, person and distinct id
with self.assertNumQueries(7):
response = self.client.get(f"/api/projects/{self.team.id}/events/?event=event_name").json()
self.assertEqual(response["results"][0]["event"], "event_name")

Expand All @@ -123,9 +123,9 @@ def test_filter_events_by_properties(self):
flush_persons_and_events()

# Django session, PostHog user, PostHog team, PostHog org membership,
# look up if rate limit is enabled (cached after first lookup), 5x non-cached instance
# look up if rate limit is enabled (cached after first lookup), instance
# setting (poe, rate limit), person and distinct id
expected_queries = 12
expected_queries = 8

with self.assertNumQueries(expected_queries):
response = self.client.get(
Expand Down
4 changes: 2 additions & 2 deletions posthog/api/test/test_person.py
Original file line number Diff line number Diff line change
Expand Up @@ -792,7 +792,7 @@ def test_pagination_limit(self):
create_person(team_id=self.team.pk, version=0)

returned_ids = []
with self.assertNumQueries(10):
with self.assertNumQueries(7):
response = self.client.get("/api/person/?limit=10").json()
self.assertEqual(len(response["results"]), 9)
returned_ids += [x["distinct_ids"][0] for x in response["results"]]
Expand All @@ -803,7 +803,7 @@ def test_pagination_limit(self):
created_ids.reverse() # ids are returned in desc order
self.assertEqual(returned_ids, created_ids, returned_ids)

with self.assertNumQueries(9):
with self.assertNumQueries(6):
response_include_total = self.client.get("/api/person/?limit=10&include_total").json()
self.assertEqual(response_include_total["count"], 20) # With `include_total`, the total count is returned too

Expand Down
3 changes: 3 additions & 0 deletions posthog/models/instance_setting.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import json
from contextlib import contextmanager
from functools import lru_cache
from typing import Any

from django.db import models
Expand All @@ -19,6 +20,7 @@ def value(self):
return json.loads(self.raw_value)


@lru_cache
def get_instance_setting(key: str) -> Any:
assert key in CONSTANCE_CONFIG, f"Unknown dynamic setting: {repr(key)}"

Expand Down Expand Up @@ -47,6 +49,7 @@ def set_instance_setting(key: str, value: Any):
InstanceSetting.objects.update_or_create(
key=CONSTANCE_DATABASE_PREFIX + key, defaults={"raw_value": json.dumps(value)}
)
get_instance_setting.cache_clear()


@contextmanager
Expand Down
2 changes: 1 addition & 1 deletion posthog/session_recordings/test/test_session_recordings.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ def test_listing_recordings_is_not_nplus1_for_persons(self):
self.client.get(f"/api/projects/{self.team.id}/session_recordings")

base_time = (now() - relativedelta(days=1)).replace(microsecond=0)
num_queries = FuzzyInt(12, 26) # PoE on or off adds queries here :shrug:
num_queries = FuzzyInt(7, 26) # PoE on or off adds queries here :shrug:

# loop from 1 to 10
for i in range(1, 11):
Expand Down
2 changes: 2 additions & 0 deletions posthog/test/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,8 @@ def setUpTestData(cls):
_setup_test_data(cls)

def setUp(self):
get_instance_setting.cache_clear()

if get_instance_setting("PERSON_ON_EVENTS_ENABLED"):
from posthog.models.team import util

Expand Down
2 changes: 1 addition & 1 deletion posthog/test/test_middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ class TestAutoProjectMiddleware(APIBaseTest):
@classmethod
def setUpTestData(cls):
super().setUpTestData()
cls.base_app_num_queries = 43
cls.base_app_num_queries = 41
# Create another team that the user does have access to
cls.second_team = create_team(organization=cls.organization, name="Second Life")

Expand Down