more progress

This commit is contained in:
Jedrzej Kosinski 2026-01-15 18:16:00 -08:00
parent f14129947c
commit e527b72b09
2 changed files with 42 additions and 1 deletions

View File

@ -1,9 +1,11 @@
import os
import sqlalchemy as sa
from collections import defaultdict
from datetime import datetime
from sqlalchemy import select, exists, func
from sqlalchemy.orm import Session, contains_eager, noload
from app.assets.database.models import Asset, AssetInfo, AssetCacheState, AssetInfoMeta, AssetInfoTag, Tag
from app.assets.helpers import escape_like_prefix, normalize_tags
from app.assets.helpers import escape_like_prefix, normalize_tags, utcnow
from typing import Sequence
@ -42,6 +44,7 @@ def apply_tag_filters(
)
return stmt
def apply_metadata_filter(
stmt: sa.sql.Select,
metadata_filter: dict | None = None,
@ -105,9 +108,11 @@ def asset_exists_by_hash(session: Session, asset_hash: str) -> bool:
).first()
return row is not None
def get_asset_info_by_id(session: Session, asset_info_id: str) -> AssetInfo | None:
return session.get(AssetInfo, asset_info_id)
def list_asset_infos_page(
session: Session,
owner_id: str = "",
@ -177,6 +182,7 @@ def list_asset_infos_page(
return infos, tag_map, total
def fetch_asset_info_asset_and_tags(
session: Session,
asset_info_id: str,
@ -208,6 +214,7 @@ def fetch_asset_info_asset_and_tags(
tags.append(tag_name)
return first_info, first_asset, tags
def fetch_asset_info_and_asset(
session: Session,
*,
@ -241,6 +248,23 @@ def list_cache_states_by_asset_id(
)
).scalars().all()
def touch_asset_info_by_id(
session: Session,
*,
asset_info_id: str,
ts: datetime | None = None,
only_if_newer: bool = True,
) -> None:
ts = ts or utcnow()
stmt = sa.update(AssetInfo).where(AssetInfo.id == asset_info_id)
if only_if_newer:
stmt = stmt.where(
sa.or_(AssetInfo.last_access_time.is_(None), AssetInfo.last_access_time < ts)
)
session.execute(stmt.values(last_access_time=ts))
def list_tags_with_usage(
session: Session,
prefix: str | None = None,
@ -298,3 +322,19 @@ def list_tags_with_usage(
rows_norm = [(name, ttype, int(count or 0)) for (name, ttype, count) in rows]
return rows_norm, int(total or 0)
def pick_best_live_path(states: Sequence[AssetCacheState]) -> str:
"""
Return the best on-disk path among cache states:
1) Prefer a path that exists with needs_verify == False (already verified).
2) Otherwise, pick the first path that exists.
3) Otherwise return empty string.
"""
alive = [s for s in states if getattr(s, "file_path", None) and os.path.isfile(s.file_path)]
if not alive:
return ""
for s in alive:
if not getattr(s, "needs_verify", False):
return s.file_path
return alive[0].file_path

View File

@ -11,6 +11,7 @@ from app.assets.database.queries import (
list_cache_states_by_asset_id,
list_asset_infos_page,
list_tags_with_usage,
pick_best_live_path,
)