修正失败的任务总积分同步
This commit is contained in:
@@ -758,13 +758,13 @@ async def list_credit_ratios_grouped(
|
|||||||
):
|
):
|
||||||
result = await db.execute(select(CreditRatio))
|
result = await db.execute(select(CreditRatio))
|
||||||
ratios = result.scalars().all()
|
ratios = result.scalars().all()
|
||||||
|
|
||||||
grouped = {}
|
grouped = {}
|
||||||
for ratio in ratios:
|
for ratio in ratios:
|
||||||
if ratio.gen_type not in grouped:
|
if ratio.gen_type not in grouped:
|
||||||
grouped[ratio.gen_type] = []
|
grouped[ratio.gen_type] = []
|
||||||
grouped[ratio.gen_type].append(CreditRatioOut.model_validate(ratio))
|
grouped[ratio.gen_type].append(CreditRatioOut.model_validate(ratio))
|
||||||
|
|
||||||
return grouped
|
return grouped
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -125,6 +125,11 @@ async def list_records(
|
|||||||
description="每页返回的生成记录数量,范围 1~100",
|
description="每页返回的生成记录数量,范围 1~100",
|
||||||
examples=[10],
|
examples=[10],
|
||||||
),
|
),
|
||||||
|
record_ids: list[str] | None = Query(
|
||||||
|
None,
|
||||||
|
description="对应记录ID数组",
|
||||||
|
examples=[["0019e8c55ddd1429b86", "0019e8c54dfc1e13262"]],
|
||||||
|
),
|
||||||
current_user: User = Depends(get_current_user),
|
current_user: User = Depends(get_current_user),
|
||||||
db: AsyncSession = Depends(get_db),
|
db: AsyncSession = Depends(get_db),
|
||||||
):
|
):
|
||||||
@@ -155,6 +160,9 @@ async def list_records(
|
|||||||
if status:
|
if status:
|
||||||
conditions.append(GenerationRecord.status == status)
|
conditions.append(GenerationRecord.status == status)
|
||||||
|
|
||||||
|
if record_ids:
|
||||||
|
conditions.append(GenerationRecord.id.in_(record_ids))
|
||||||
|
|
||||||
total_result = await db.execute(
|
total_result = await db.execute(
|
||||||
select(func.count(GenerationRecord.id))
|
select(func.count(GenerationRecord.id))
|
||||||
.join(Project, GenerationRecord.project_id == Project.id)
|
.join(Project, GenerationRecord.project_id == Project.id)
|
||||||
@@ -291,10 +299,40 @@ async def optimize(
|
|||||||
db, token_usage["input_tokens"], token_usage["output_tokens"],
|
db, token_usage["input_tokens"], token_usage["output_tokens"],
|
||||||
)
|
)
|
||||||
|
|
||||||
await deduct_credits(
|
failed_record_id = record.id
|
||||||
db, current_user.id, text_credits,
|
failed_user_id = current_user.id
|
||||||
f"提示词优化 - {project.name}",
|
try:
|
||||||
)
|
await deduct_credits(
|
||||||
|
db, current_user.id, text_credits,
|
||||||
|
f"提示词优化 - {project.name}",
|
||||||
|
)
|
||||||
|
except InsufficientCreditsError as e:
|
||||||
|
# /optimize 阶段只处理提示词优化扣费。
|
||||||
|
# 提示词积分不足时,之前已落库的 optimizing 记录必须改为 failed,避免前端长期显示生成中。
|
||||||
|
# 此阶段没有媒体生成扣费,不调用生成失败退款逻辑。
|
||||||
|
await db.rollback()
|
||||||
|
result = await db.execute(
|
||||||
|
select(GenerationRecord)
|
||||||
|
.where(
|
||||||
|
GenerationRecord.id == failed_record_id,
|
||||||
|
GenerationRecord.user_id == failed_user_id,
|
||||||
|
GenerationRecord.deleted_at.is_(None),
|
||||||
|
)
|
||||||
|
.with_for_update()
|
||||||
|
.limit(1)
|
||||||
|
)
|
||||||
|
failed_record = result.scalar_one_or_none()
|
||||||
|
if failed_record:
|
||||||
|
failed_record.status = "failed"
|
||||||
|
failed_record.error_message = e.detail
|
||||||
|
failed_record.optimized_prompt = None
|
||||||
|
failed_record.text_credits_cost = 0
|
||||||
|
failed_record.credits_cost = 0
|
||||||
|
failed_record.text_tokens_used = token_usage.get("total_tokens", 0)
|
||||||
|
await db.flush()
|
||||||
|
# 这里必须主动提交,否则后续抛出 402 后 get_db 会 rollback,failed 状态会被回滚。
|
||||||
|
await db.commit()
|
||||||
|
raise e
|
||||||
|
|
||||||
record.optimized_prompt = optimized
|
record.optimized_prompt = optimized
|
||||||
record.status = "prompt_optimized"
|
record.status = "prompt_optimized"
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ async def refund_unrefunded_media_charges(
|
|||||||
db,
|
db,
|
||||||
user_id=user_id,
|
user_id=user_id,
|
||||||
amount=amount,
|
amount=amount,
|
||||||
description=f"{description_prefix}失败积分回退 attempt:{attempt_no}",
|
description=f"{description_prefix}失败积分回退",
|
||||||
related_id=owner_id,
|
related_id=owner_id,
|
||||||
biz_key=refund_biz_key,
|
biz_key=refund_biz_key,
|
||||||
refund_for_biz_key=charge.biz_key,
|
refund_for_biz_key=charge.biz_key,
|
||||||
@@ -149,13 +149,17 @@ async def mark_generation_record_failed_and_refund_once(
|
|||||||
if error_message:
|
if error_message:
|
||||||
record.error_message = error_message
|
record.error_message = error_message
|
||||||
|
|
||||||
await refund_unrefunded_media_charges(
|
refunded_amount = await refund_unrefunded_media_charges(
|
||||||
db,
|
db,
|
||||||
user_id=record.user_id,
|
user_id=record.user_id,
|
||||||
owner_type=OWNER_GENERATION_RECORD,
|
owner_type=OWNER_GENERATION_RECORD,
|
||||||
owner_id=record.id,
|
owner_id=record.id,
|
||||||
description_prefix="生成记录",
|
description_prefix="生成记录",
|
||||||
)
|
)
|
||||||
|
if refunded_amount > 0:
|
||||||
|
# GenerationRecord.credits_cost 只代表视频/图片生成媒体积分。
|
||||||
|
# 提示词优化积分在 text_credits_cost 中记录,优化成功后不参与生成失败退款。
|
||||||
|
record.credits_cost = max(0.0, round(float(record.credits_cost or 0) - refunded_amount, 2))
|
||||||
await db.flush()
|
await db.flush()
|
||||||
return record
|
return record
|
||||||
|
|
||||||
@@ -194,12 +198,15 @@ async def mark_chat_generation_task_failed_and_refund_once(
|
|||||||
if error_message:
|
if error_message:
|
||||||
task.error_message = error_message
|
task.error_message = error_message
|
||||||
|
|
||||||
await refund_unrefunded_media_charges(
|
refunded_amount = await refund_unrefunded_media_charges(
|
||||||
db,
|
db,
|
||||||
user_id=task.user_id,
|
user_id=task.user_id,
|
||||||
owner_type=OWNER_CHAT_GENERATION_TASK,
|
owner_type=OWNER_CHAT_GENERATION_TASK,
|
||||||
owner_id=task.id,
|
owner_id=task.id,
|
||||||
description_prefix="Chat生成任务",
|
description_prefix="Chat生成任务",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if refunded_amount > 0:
|
||||||
|
task.credits_cost = max(0.0, round(float(task.credits_cost or 0) - refunded_amount, 2))
|
||||||
await db.flush()
|
await db.flush()
|
||||||
return task
|
return task
|
||||||
|
|||||||
Reference in New Issue
Block a user