55 lines
1.4 KiB
Python
55 lines
1.4 KiB
Python
"""AI Steward 上下文缓存服务(Redis)与失效钩子。"""
|
||
|
||
from __future__ import annotations
|
||
|
||
import json
|
||
import os
|
||
import re
|
||
from datetime import datetime, timezone
|
||
from pathlib import Path
|
||
from typing import Any, Optional
|
||
|
||
from sqlalchemy import and_, case, event, func, inspect, or_, select
|
||
from sqlalchemy.ext.asyncio import AsyncSession
|
||
from sqlalchemy.orm import Session
|
||
|
||
from ...models import Project, ProjectSignalLink, Signal, Task, User, UserProject, UserWorkload
|
||
|
||
from ...utils.timezone import now_cn_aware
|
||
try:
|
||
import redis.asyncio as redis_async
|
||
from redis import Redis as RedisSync
|
||
|
||
REDIS_AVAILABLE = True
|
||
except Exception: # pragma: no cover
|
||
REDIS_AVAILABLE = False
|
||
redis_async = None
|
||
RedisSync = None
|
||
|
||
|
||
SYSTEM_TTL_SECONDS = 30 * 60
|
||
USER_TTL_SECONDS = 5 * 60
|
||
SESSION_TTL_SECONDS = 60 * 60
|
||
PROJECT_LIST_TTL_SECONDS = 10 * 60
|
||
SIGNAL_PENDING_TTL_SECONDS = 5 * 60
|
||
SESSION_MAX_MESSAGES = 20
|
||
DONE_TASK_STATUSES = {"done", "completed", "closed", "resolved", "archived"}
|
||
PENDING_SIGNAL_STATUSES = {"pending", "todo", "open", "待处理"}
|
||
|
||
|
||
def _safe_int(value: Any, fallback: int = 0) -> int:
|
||
try:
|
||
return int(value)
|
||
except Exception:
|
||
return fallback
|
||
|
||
|
||
def _json_loads(raw: Optional[str], default: Any) -> Any:
|
||
if not raw:
|
||
return default
|
||
try:
|
||
return json.loads(raw)
|
||
except Exception:
|
||
return default
|
||
|