From e527b72b098863f3cd8e7341ffb655b97f383835 Mon Sep 17 00:00:00 2001 From: Jedrzej Kosinski Date: Thu, 15 Jan 2026 18:16:00 -0800 Subject: [PATCH] more progress --- app/assets/database/queries.py | 42 +++++++++++++++++++++++++++++++++- app/assets/manager.py | 1 + 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/app/assets/database/queries.py b/app/assets/database/queries.py index 086b7010c..474b3f7e7 100644 --- a/app/assets/database/queries.py +++ b/app/assets/database/queries.py @@ -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 diff --git a/app/assets/manager.py b/app/assets/manager.py index 1db25be11..b64c6dcc4 100644 --- a/app/assets/manager.py +++ b/app/assets/manager.py @@ -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, )