生成项目任务/chat任务软删|生成资源管控回收|生成资源token验签API预处理
This commit is contained in:
@@ -28,6 +28,11 @@ from app.schemas.generation import (
|
||||
from app.services.credits import deduct_credits, calc_text_credits, calc_video_credits, calc_image_credits
|
||||
from app.services.llm import optimize_prompt
|
||||
from app.services.video_url import generate_temp_url, validate_and_get_record_id, get_video_stream_url
|
||||
from app.services.resource_accounting_service import (
|
||||
record_generation_record_generated_resource,
|
||||
safe_file_size,
|
||||
)
|
||||
from app.services.resource_signed_url_service import build_resource_signed_url
|
||||
from app.utils.id_gen import generate_id
|
||||
from app.utils.exceptions import InsufficientCreditsError, RecordNotFoundError, InvalidStatusError
|
||||
|
||||
@@ -71,8 +76,8 @@ def _record_to_out(record: GenerationRecord, project_name: str) -> GenerationRec
|
||||
image_proportion=record.image_proportion,
|
||||
image_px=record.image_px,
|
||||
status=record.status,
|
||||
video_url=record.video_url,
|
||||
image_url=record.image_url,
|
||||
video_url=build_resource_signed_url(record.video_url) if record.video_url else '',
|
||||
image_url=build_resource_signed_url(record.image_url) if record.image_url else '',
|
||||
references=refs,
|
||||
text_credits_cost=round(record.text_credits_cost or 0.00, 2),
|
||||
# text_tokens_used=record.text_tokens_used or 0,
|
||||
@@ -94,7 +99,11 @@ async def list_records(
|
||||
query = (
|
||||
select(GenerationRecord, Project.name)
|
||||
.join(Project, GenerationRecord.project_id == Project.id)
|
||||
.where(GenerationRecord.user_id == current_user.id)
|
||||
.where(
|
||||
GenerationRecord.user_id == current_user.id,
|
||||
GenerationRecord.deleted_at.is_(None),
|
||||
Project.deleted_at.is_(None),
|
||||
)
|
||||
.order_by(GenerationRecord.created_at.desc())
|
||||
)
|
||||
if project_id:
|
||||
@@ -133,6 +142,8 @@ async def optimize(
|
||||
.join(Project, GenerationRecord.project_id == Project.id)
|
||||
.where(
|
||||
GenerationRecord.user_id == current_user.id,
|
||||
GenerationRecord.deleted_at.is_(None),
|
||||
Project.deleted_at.is_(None),
|
||||
GenerationRecord.idempotency_key == req.idempotency_key,
|
||||
GenerationRecord.gen_type == req.gen_type,
|
||||
GenerationRecord.status == "prompt_optimized",
|
||||
@@ -155,6 +166,7 @@ async def optimize(
|
||||
select(Project).where(
|
||||
Project.id == req.project_id,
|
||||
Project.user_id == current_user.id,
|
||||
Project.deleted_at.is_(None),
|
||||
)
|
||||
)
|
||||
project = proj_result.scalar_one_or_none()
|
||||
@@ -243,6 +255,8 @@ async def generate(
|
||||
.where(
|
||||
GenerationRecord.id == record_id,
|
||||
GenerationRecord.user_id == current_user.id,
|
||||
GenerationRecord.deleted_at.is_(None),
|
||||
Project.deleted_at.is_(None),
|
||||
)
|
||||
)
|
||||
row = result.first()
|
||||
@@ -326,6 +340,8 @@ async def retry_generation(
|
||||
.where(
|
||||
GenerationRecord.id == record_id,
|
||||
GenerationRecord.user_id == current_user.id,
|
||||
GenerationRecord.deleted_at.is_(None),
|
||||
Project.deleted_at.is_(None),
|
||||
)
|
||||
)
|
||||
row = result.first()
|
||||
@@ -378,6 +394,7 @@ async def update_prompt(
|
||||
select(GenerationRecord).where(
|
||||
GenerationRecord.id == record_id,
|
||||
GenerationRecord.user_id == current_user.id,
|
||||
GenerationRecord.deleted_at.is_(None),
|
||||
)
|
||||
)
|
||||
record = result.scalar_one_or_none()
|
||||
@@ -422,6 +439,7 @@ async def get_queue_status(
|
||||
select(GenerationRecord).where(
|
||||
GenerationRecord.id == record_id,
|
||||
GenerationRecord.user_id == current_user.id,
|
||||
GenerationRecord.deleted_at.is_(None),
|
||||
)
|
||||
)
|
||||
record = result.scalar_one_or_none()
|
||||
@@ -435,6 +453,7 @@ async def get_queue_status(
|
||||
ahead_result = await db.execute(
|
||||
select(func.count(GenerationRecord.id)).where(
|
||||
GenerationRecord.status == "generating",
|
||||
GenerationRecord.deleted_at.is_(None),
|
||||
GenerationRecord.created_at < record.created_at,
|
||||
)
|
||||
)
|
||||
@@ -461,7 +480,10 @@ async def seedance_callback(request: Request, db: AsyncSession = Depends(get_db)
|
||||
return {"message": "ignored"}
|
||||
|
||||
result = await db.execute(
|
||||
select(GenerationRecord).where(GenerationRecord.seedance_task_id == task_id)
|
||||
select(GenerationRecord).where(
|
||||
GenerationRecord.seedance_task_id == task_id,
|
||||
GenerationRecord.deleted_at.is_(None),
|
||||
)
|
||||
)
|
||||
record = result.scalar_one_or_none()
|
||||
if not record:
|
||||
@@ -470,19 +492,33 @@ async def seedance_callback(request: Request, db: AsyncSession = Depends(get_db)
|
||||
if task_status == "succeeded":
|
||||
remote_url = data.get("content", {}).get("video_url", "")
|
||||
record.status = "completed"
|
||||
storage_path = None
|
||||
file_size_bytes = 0
|
||||
# Download video to local storage
|
||||
if settings.STORAGE_TYPE == "local" and remote_url:
|
||||
try:
|
||||
from app.services.video_gen import download_video
|
||||
dest = os.path.join(settings.STORAGE_LOCAL_PATH, f"{record.id}.mp4")
|
||||
await download_video(remote_url, dest)
|
||||
record.video_url = f"/videos/{record.id}.mp4"
|
||||
record.video_url = f"/generate/videos/{record.id}.mp4"
|
||||
storage_path = dest
|
||||
file_size_bytes = safe_file_size(dest)
|
||||
except Exception as e:
|
||||
logger.warning(f"Callback download failed, using remote URL: {e}")
|
||||
record.video_url = remote_url
|
||||
else:
|
||||
record.video_url = remote_url
|
||||
record.generated_at = datetime.now()
|
||||
if record.video_url:
|
||||
await record_generation_record_generated_resource(
|
||||
db,
|
||||
record,
|
||||
resource_url=record.video_url,
|
||||
storage_path=storage_path,
|
||||
file_size_bytes=file_size_bytes,
|
||||
remote_url=remote_url,
|
||||
generated_at=record.generated_at,
|
||||
)
|
||||
# Extract video token usage from callback
|
||||
usage = data.get("usage", {})
|
||||
if usage:
|
||||
|
||||
Reference in New Issue
Block a user