perf: bound public activity aggregation
This commit is contained in:
@@ -10,6 +10,8 @@ from sqlalchemy.orm import Session, joinedload
|
||||
from .models import CatchReport, ModerationStatus
|
||||
from .schemas import ActivityOut
|
||||
|
||||
MAX_ACTIVITY_FACTS = 10_000
|
||||
|
||||
|
||||
def activity_rows(
|
||||
session: Session,
|
||||
@@ -33,6 +35,8 @@ def activity_rows(
|
||||
CatchReport.spot_id.is_not(None),
|
||||
CatchReport.reported_at >= now - timedelta(hours=hours),
|
||||
)
|
||||
.order_by(CatchReport.reported_at.desc(), CatchReport.id.desc())
|
||||
.limit(MAX_ACTIVITY_FACTS)
|
||||
)
|
||||
if waterbody:
|
||||
query = query.where(CatchReport.waterbody.has(slug=waterbody))
|
||||
|
||||
@@ -12,6 +12,7 @@ TACKLE_MEDIA_ROLES = {"tackle_card", "tackle_detail", "rig_diagram", "tackle_scr
|
||||
KNOWN_MEDIA_ROLES = WATERBODY_MEDIA_ROLES | TACKLE_MEDIA_ROLES
|
||||
MEDIA_ROLES_BY_ENTITY = {"waterbody": WATERBODY_MEDIA_ROLES, "tackle": TACKLE_MEDIA_ROLES}
|
||||
_manifest_cache: tuple[Path, int, int, dict] | None = None
|
||||
_asset_index_cache: tuple[int, dict[str, tuple[str, str | None]]] | None = None
|
||||
|
||||
|
||||
def _read_manifest() -> dict:
|
||||
@@ -107,21 +108,23 @@ def published_file(digest: str) -> tuple[Path, str] | None:
|
||||
if len(digest) != 64 or any(char not in "0123456789abcdef" for char in digest):
|
||||
return None
|
||||
manifest = _read_manifest()
|
||||
item = next((row for row in manifest.get("assets", []) if row.get("status") == "approved" and row.get("sha256") == digest), None)
|
||||
media_type = None
|
||||
local_path = None
|
||||
if item:
|
||||
media_type = item.get("content_type")
|
||||
local_path = item.get("local_path")
|
||||
else:
|
||||
global _asset_index_cache
|
||||
cache_key = id(manifest)
|
||||
if _asset_index_cache is None or _asset_index_cache[0] != cache_key:
|
||||
index: dict[str, tuple[str, str | None]] = {}
|
||||
for row in manifest.get("assets", []):
|
||||
if row.get("status") != "approved":
|
||||
continue
|
||||
variant = next((candidate for candidate in row.get("derivatives", []) if candidate.get("sha256") == digest), None)
|
||||
if variant:
|
||||
media_type = variant.get("content_type")
|
||||
local_path = variant.get("local_path")
|
||||
break
|
||||
if row.get("sha256") and row.get("local_path"):
|
||||
index[str(row["sha256"])] = (str(row["local_path"]), row.get("content_type"))
|
||||
for variant in row.get("derivatives", []):
|
||||
if variant.get("sha256") and variant.get("local_path"):
|
||||
index.setdefault(str(variant["sha256"]), (str(variant["local_path"]), variant.get("content_type")))
|
||||
_asset_index_cache = (cache_key, index)
|
||||
asset = _asset_index_cache[1].get(digest)
|
||||
if asset is None:
|
||||
return None
|
||||
local_path, media_type = asset
|
||||
if not local_path:
|
||||
return None
|
||||
target = (MEDIA_ROOT / local_path).resolve()
|
||||
|
||||
@@ -14,6 +14,7 @@ from ..schemas import TackleCombinationOut
|
||||
|
||||
router = APIRouter()
|
||||
FRESHNESS_HALF_LIFE_HOURS = 12.5
|
||||
MAX_ANALYTICS_FACTS = 10_000
|
||||
|
||||
|
||||
def _age_hours(value: datetime, now: datetime) -> float:
|
||||
@@ -53,6 +54,7 @@ def tackle_combinations(
|
||||
query = query.join(Fish, CatchReport.fish_id == Fish.id).where(Fish.slug == fish)
|
||||
if method:
|
||||
query = query.where(CatchReport.fishing_method == method)
|
||||
query = query.order_by(CatchReport.caught_at.desc(), CatchReport.reported_at.desc(), CatchReport.id.desc()).limit(MAX_ANALYTICS_FACTS)
|
||||
|
||||
groups: dict[tuple[str, str], list[CatchReport]] = defaultdict(list)
|
||||
for report in db.scalars(query):
|
||||
|
||||
Reference in New Issue
Block a user