diff --git a/posthog/api/query.py b/posthog/api/query.py index 0db629e22a4415..c5dcd276cc0259 100644 --- a/posthog/api/query.py +++ b/posthog/api/query.py @@ -3,7 +3,7 @@ from django.http import JsonResponse from drf_spectacular.utils import OpenApiResponse -from posthog.hogql_queries.query_runner import RecalculationMode +from posthog.hogql_queries.query_runner import ExecutionMode from rest_framework import viewsets from rest_framework.decorators import action from rest_framework.exceptions import ValidationError, NotAuthenticated @@ -79,7 +79,7 @@ def create(self, request, *args, **kwargs) -> Response: result = process_query_model( self.team, data.query, - recalculation_mode=RecalculationMode.REQUEST if data.refresh else RecalculationMode.NEVER, + execution_mode=ExecutionMode.CALCULATION_REQUESTED if data.refresh else ExecutionMode.CACHE_ONLY, ) return Response(result) except (ExposedHogQLError, ExposedCHQueryError) as e: diff --git a/posthog/api/services/query.py b/posthog/api/services/query.py index 1b84eae04d7247..2387791e99d98a 100644 --- a/posthog/api/services/query.py +++ b/posthog/api/services/query.py @@ -11,7 +11,7 @@ from posthog.hogql.autocomplete import get_hogql_autocomplete from posthog.hogql.metadata import get_hogql_metadata from posthog.hogql.modifiers import create_default_modifiers_for_team -from posthog.hogql_queries.query_runner import RecalculationMode, get_query_runner +from posthog.hogql_queries.query_runner import ExecutionMode, get_query_runner from posthog.models import Team from posthog.queries.time_to_see_data.serializers import SessionEventsQuerySerializer, SessionsQuerySerializer from posthog.queries.time_to_see_data.sessions import get_session_events, get_sessions @@ -61,7 +61,7 @@ def process_query( query_json: dict, *, limit_context: Optional[LimitContext] = None, - recalculation_mode: RecalculationMode = RecalculationMode.IF_STALE, + execution_mode: ExecutionMode = ExecutionMode.CALCULATION_ONLY_IF_STALE, ) -> dict: model = QuerySchemaRoot.model_validate(query_json) tag_queries(query=query_json) @@ -69,7 +69,7 @@ def process_query( team, model.root, limit_context=limit_context, - recalculation_mode=recalculation_mode, + execution_mode=execution_mode, ) @@ -78,13 +78,13 @@ def process_query_model( query: BaseModel, # mypy has problems with unions and isinstance *, limit_context: Optional[LimitContext] = None, - recalculation_mode: RecalculationMode = RecalculationMode.IF_STALE, + execution_mode: ExecutionMode = ExecutionMode.CALCULATION_ONLY_IF_STALE, ) -> dict: result: dict | BaseModel if isinstance(query, QUERY_WITH_RUNNER): # type: ignore query_runner = get_query_runner(query, team, limit_context=limit_context) - result = query_runner.run(recalculation_mode=recalculation_mode) + result = query_runner.run(execution_mode=execution_mode) elif isinstance(query, QUERY_WITH_RUNNER_NO_CACHE): # type: ignore query_runner = get_query_runner(query, team, limit_context=limit_context) result = query_runner.calculate() diff --git a/posthog/caching/calculate_results.py b/posthog/caching/calculate_results.py index 958cae8aa50887..47577b0ca6d6f9 100644 --- a/posthog/caching/calculate_results.py +++ b/posthog/caching/calculate_results.py @@ -1,6 +1,6 @@ from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple, Union -from posthog.api.services.query import RecalculationMode +from posthog.api.services.query import ExecutionMode import structlog from sentry_sdk import capture_exception @@ -116,7 +116,7 @@ def calculate_for_query_based_insight(insight: Insight, *, refresh_requested: bo response = process_query( insight.team, insight.query, - recalculation_mode=RecalculationMode.REQUEST if refresh_requested else RecalculationMode.NEVER, + execution_mode=ExecutionMode.CALCULATION_REQUESTED if refresh_requested else ExecutionMode.CACHE_ONLY, ) if "results" not in response: diff --git a/posthog/clickhouse/client/execute_async.py b/posthog/clickhouse/client/execute_async.py index 5f335bfad0ef41..118ac10cef2fd6 100644 --- a/posthog/clickhouse/client/execute_async.py +++ b/posthog/clickhouse/client/execute_async.py @@ -81,7 +81,7 @@ def execute_process_query( ): manager = QueryStatusManager(query_id, team_id) - from posthog.api.services.query import process_query, RecalculationMode + from posthog.api.services.query import process_query, ExecutionMode from posthog.models import Team team = Team.objects.get(pk=team_id) @@ -104,7 +104,7 @@ def execute_process_query( team=team, query_json=query_json, limit_context=limit_context, - recalculation_mode=RecalculationMode.REQUEST if refresh_requested else RecalculationMode.NEVER, + execution_mode=ExecutionMode.CALCULATION_REQUESTED if refresh_requested else ExecutionMode.CACHE_ONLY, ) logger.info("Got results for team %s query %s", team_id, query_id) query_status.complete = True diff --git a/posthog/hogql_queries/query_runner.py b/posthog/hogql_queries/query_runner.py index 10072d813a8cc4..ed8dc860d06065 100644 --- a/posthog/hogql_queries/query_runner.py +++ b/posthog/hogql_queries/query_runner.py @@ -1,6 +1,6 @@ from abc import ABC, abstractmethod from datetime import datetime -from enum import Enum, auto +from enum import IntEnum from typing import Any, Generic, List, Optional, Type, Dict, TypeVar, Union, Tuple, cast, TypeGuard from django.conf import settings @@ -58,13 +58,13 @@ DataT = TypeVar("DataT") -class RecalculationMode(Enum): - REQUEST = auto() - """Always recalculate, except if a VERY recent result is present in cache.""" - IF_STALE = auto() - """Use cache, unless the results are stale or missing.""" - NEVER = auto() - """Only use cache.""" +class ExecutionMode(IntEnum): + CALCULATION_REQUESTED = 2 + """Always recalculate, except if very recent results are present in cache.""" + CALCULATION_ONLY_IF_STALE = 1 + """Use cache, unless the results are missing or stale.""" + CACHE_ONLY = 0 + """Do not initiate calculation.""" class QueryResponse(BaseModel, Generic[DataT]): @@ -318,12 +318,12 @@ def calculate(self) -> BaseModel: raise NotImplementedError() def run( - self, recalculation_mode: RecalculationMode = RecalculationMode.IF_STALE + self, execution_mode: ExecutionMode = ExecutionMode.CALCULATION_ONLY_IF_STALE ) -> CachedQueryResponse | CacheMissResponse: cache_key = f"{self._cache_key()}_{self.limit_context or LimitContext.QUERY}" tag_queries(cache_key=cache_key) - if recalculation_mode != RecalculationMode.REQUEST: + if execution_mode != ExecutionMode.CALCULATION_REQUESTED: cached_response = get_safe_cache(cache_key) if cached_response: if not self._is_stale(cached_response): @@ -334,7 +334,7 @@ def run( QUERY_CACHE_HIT_COUNTER.labels(team_id=self.team.pk, cache_hit="stale").inc() else: QUERY_CACHE_HIT_COUNTER.labels(team_id=self.team.pk, cache_hit="miss").inc() - if recalculation_mode == RecalculationMode.NEVER: + if execution_mode == ExecutionMode.CACHE_ONLY: return CacheMissResponse(cache_key=cache_key) fresh_response_dict = cast(QueryResponse, self.calculate()).model_dump()