用户生成资源容量管控

This commit is contained in:
2026-06-29 13:50:39 +08:00
parent b21f35582e
commit 25fa41f894
21 changed files with 1314 additions and 80 deletions
+15 -2
View File
@@ -49,6 +49,7 @@ from app.services.auth import hash_password, verify_password
from app.services.operation_log import log_operation
from app.services.resource_signed_url_service import build_resource_signed_url
from app.services.payment import sync_pending_orders, process_refund
from app.services.resource_capacity_service import batch_get_user_resource_capacity_usage, get_user_resource_capacity_usage
from app.services.generation_billing_service import (
OWNER_GENERATION_RECORD,
@@ -107,7 +108,16 @@ async def list_users(
total = (await db.execute(count_query)).scalar() or 0
result = await db.execute(query.offset((page - 1) * page_size).limit(page_size))
items = result.scalars().all()
return {"items": [AdminUserOut.model_validate(u) for u in items], "total": total}
capacity_map = await batch_get_user_resource_capacity_usage(db, [u.id for u in items])
return {
"items": [
AdminUserOut.model_validate(u)
.model_copy(update={"resource_capacity": capacity_map.get(u.id)})
.model_dump(mode="json")
for u in items
],
"total": total,
}
@router.post("/users", response_model=AdminUserOut)
@@ -183,7 +193,10 @@ async def get_user(
if not user:
raise HTTPException(status_code=404, detail="用户不存在")
user.credits = round(user.credits, 2)
return user
resource_capacity = await get_user_resource_capacity_usage(db, user.id)
return AdminUserOut.model_validate(user).model_copy(
update={"resource_capacity": resource_capacity}
)
@router.post("/users/{user_id}/credits")
+9 -2
View File
@@ -30,6 +30,7 @@ from app.services.auth import (
verify_password,
)
from app.services.sms import verify_sms_code
from app.services.resource_capacity_service import get_user_resource_capacity_usage
from app.utils.id_gen import generate_id
router = APIRouter(prefix="/auth", tags=["auth"])
@@ -248,9 +249,15 @@ async def logout(current_user: User = Depends(get_current_user_allow_password_pe
@router.get("/me", response_model=UserOut)
async def get_me(current_user: User = Depends(get_current_user_allow_password_pending)):
async def get_me(
current_user: User = Depends(get_current_user_allow_password_pending),
db: AsyncSession = Depends(get_db),
):
current_user.credits = round(current_user.credits, 2)
return current_user
resource_capacity = await get_user_resource_capacity_usage(db, current_user.id)
return UserOut.model_validate(current_user).model_copy(
update={"resource_capacity": resource_capacity}
)
@router.post(
+5
View File
@@ -34,6 +34,7 @@ from app.services.resource_accounting_service import (
safe_file_size,
)
from app.services.resource_signed_url_service import build_resource_signed_url
from app.services.resource_capacity_service import assert_user_resource_capacity_available
from app.services.generation_billing_service import (
CHARGE_TEXT_PROMPT,
OWNER_GENERATION_RECORD,
@@ -398,6 +399,8 @@ async def generate(
if record.status not in ("prompt_optimized", "failed"):
raise InvalidStatusError("当前状态不允许生成")
await assert_user_resource_capacity_available(db, current_user.id)
attempt_no = await get_next_credit_attempt_no(
db,
owner_type=OWNER_GENERATION_RECORD,
@@ -522,6 +525,8 @@ async def retry_generation(
if record.status != "failed":
raise InvalidStatusError("只有失败的记录可以重试")
await assert_user_resource_capacity_available(db, current_user.id)
attempt_no = await get_next_credit_attempt_no(
db,
owner_type=OWNER_GENERATION_RECORD,
@@ -33,6 +33,7 @@ from app.services.generation_billing_service import (
)
from app.services.generation_log_service import log_task_event
from app.services.generation_refund_service import mark_chat_generation_task_failed_and_refund_once
from app.services.resource_capacity_service import assert_user_resource_capacity_available
from app.tasks.celery_app import celery_app
router = APIRouter(
@@ -566,6 +567,8 @@ async def retry_task(
if task.status != "failed":
raise HTTPException(status_code=400, detail="只有失败任务可以重试")
await assert_user_resource_capacity_available(db, current_user.id)
attempt_no = await get_next_credit_attempt_no(
db,
owner_type=OWNER_CHAT_GENERATION_TASK,