make it great agin

This commit is contained in:
Yansong Zhang
2026-02-04 11:17:30 +08:00
parent 292a9ff487
commit 240684e723
8 changed files with 631 additions and 53 deletions

View File

@ -6,58 +6,42 @@ import logging
from datetime import datetime
from celery import shared_task
from sqlalchemy import update
from sqlalchemy.orm import Session
from extensions.ext_database import db
from libs.datetime_utils import naive_utc_now
from models.model import ApiToken
from libs.api_token_updater import update_token_last_used_at
logger = logging.getLogger(__name__)
@shared_task(queue="dataset", bind=True)
@shared_task(queue="api_token_update", bind=True)
def update_api_token_last_used_task(self, token: str, scope: str | None, start_time_iso: str):
"""
Asynchronously update the last_used_at timestamp for an API token.
Uses timestamp comparison to ensure only updates when last_used_at is older
than the request start time, providing natural concurrency control.
Uses the unified update_token_last_used_at() method to avoid code duplication.
Queue: api_token_update (dedicated queue to isolate from other tasks and
prevent accumulation in production environment)
Args:
token: The API token string
scope: The token type/scope (e.g., 'app', 'dataset')
start_time_iso: ISO format timestamp of when the request started
Returns:
Dict with status and metadata
"""
try:
# Parse start_time from ISO format
start_time = datetime.fromisoformat(start_time_iso)
# Update database
current_time = naive_utc_now()
with Session(db.engine, expire_on_commit=False) as session:
update_stmt = (
update(ApiToken)
.where(
ApiToken.token == token,
ApiToken.type == scope,
(ApiToken.last_used_at.is_(None) | (ApiToken.last_used_at < start_time)),
)
.values(last_used_at=current_time)
)
result = session.execute(update_stmt)
# Check if any rows were updated
rowcount = getattr(result, "rowcount", 0)
if rowcount > 0:
session.commit()
logger.info("Updated last_used_at for token (async): %s... (scope: %s)", token[:10], scope)
return {"status": "updated", "rowcount": rowcount, "start_time": start_time_iso}
else:
logger.debug("No update needed for token: %s... (already up-to-date)", token[:10])
return {"status": "no_update_needed", "reason": "last_used_at >= start_time"}
# Use unified update method
result = update_token_last_used_at(token, scope, start_time, session=None)
if result["status"] == "updated":
logger.info("Updated last_used_at for token (async): %s... (scope: %s)", token[:10], scope)
return result
except Exception as e:
logger.warning("Failed to update last_used_at for token (async): %s", e)
# Don't retry on failure to avoid blocking the queue
return {"status": "failed", "error": str(e)}