refactor: extract generation core service
This commit is contained in:
@@ -20,6 +20,14 @@ from rest_framework.test import APIClient
|
||||
from rest_framework.views import APIView
|
||||
|
||||
from apps.api.authentication import ApiKeyAuthentication
|
||||
from apps.api.generation import (
|
||||
ApiRequestError,
|
||||
GenerationInput,
|
||||
execute_precharged_generation,
|
||||
precharge_generation,
|
||||
prepare_generation,
|
||||
run_synchronous_generation,
|
||||
)
|
||||
from apps.api.throttles import GenerateRateThrottle
|
||||
from apps.api.views import ClientLatestReleaseView, ExternalApiView, ModelsView
|
||||
from apps.ai.models import AiModel, ModelAlias
|
||||
@@ -1273,6 +1281,34 @@ class GenerateApiTests(TestCase):
|
||||
self.assertEqual(call.result_summary, "image_bytes=21")
|
||||
self.assertNotIn("SECRET_RAW", call.result_ref + call.result_summary)
|
||||
|
||||
def test_generation_core_saves_image_with_url_builder_without_request(self):
|
||||
encoded = base64.b64encode(b"input-image").decode("ascii")
|
||||
|
||||
with patch("apps.api.generation.get_provider", return_value=self.provider):
|
||||
result = run_synchronous_generation(
|
||||
GenerationInput(
|
||||
user=self.user,
|
||||
api_key=self.api_key,
|
||||
operation_type=CallRecord.OperationType.IMAGE,
|
||||
prompt="生成图片",
|
||||
alias=self.image_alias,
|
||||
resolution="1K",
|
||||
image_base64=f"data:image/png;base64,{encoded}",
|
||||
),
|
||||
image_url_builder=lambda url: f"https://cdn.example.test{url}",
|
||||
)
|
||||
|
||||
self.assertEqual(result.operation_type, CallRecord.OperationType.IMAGE)
|
||||
self.assertTrue(result.image_url.startswith("https://cdn.example.test/media/"))
|
||||
self.assertEqual(result.as_response_data()["image_url"], result.image_url)
|
||||
self.assertEqual(self.provider.image_calls[0]["image"], b"input-image")
|
||||
|
||||
call = CallRecord.objects.get(pk=result.call_record.id)
|
||||
self.assertEqual(call.status, CallRecord.Status.SUCCESS)
|
||||
self.assertEqual(call.result_ref, result.image_url)
|
||||
self.wallet.refresh_from_db()
|
||||
self.assertEqual(self.wallet.points_balance, 90)
|
||||
|
||||
def test_generate_image_downloads_safe_image_url(self):
|
||||
response = FakeImageUrlResponse(
|
||||
headers={"Content-Type": "image/jpeg"},
|
||||
@@ -1514,6 +1550,51 @@ class GenerateApiTests(TestCase):
|
||||
1,
|
||||
)
|
||||
|
||||
def test_precharged_generation_stage_refunds_on_upstream_failure(self):
|
||||
self.provider.text_error = AiProviderError("provider timeout")
|
||||
|
||||
with patch("apps.api.generation.get_provider", return_value=self.provider):
|
||||
prepared = prepare_generation(
|
||||
GenerationInput(
|
||||
user=self.user,
|
||||
api_key=self.api_key,
|
||||
operation_type=CallRecord.OperationType.TITLE,
|
||||
prompt="生成标题",
|
||||
alias=self.title_alias,
|
||||
resolution="1K",
|
||||
)
|
||||
)
|
||||
precharged = precharge_generation(prepared)
|
||||
|
||||
self.wallet.refresh_from_db()
|
||||
self.assertEqual(self.wallet.points_balance, 98)
|
||||
self.assertEqual(precharged.call_record.status, CallRecord.Status.PENDING)
|
||||
|
||||
with self.assertRaises(ApiRequestError) as captured:
|
||||
execute_precharged_generation(precharged)
|
||||
|
||||
self.assertEqual(captured.exception.code, "upstream_error")
|
||||
self.wallet.refresh_from_db()
|
||||
self.assertEqual(self.wallet.points_balance, 100)
|
||||
|
||||
call = CallRecord.objects.get(pk=precharged.call_record.id)
|
||||
self.assertEqual(call.status, CallRecord.Status.FAILED)
|
||||
self.assertIn("provider timeout", call.error_message)
|
||||
self.assertEqual(
|
||||
PointsLedger.objects.filter(
|
||||
ref_call=call,
|
||||
change_type=PointsLedger.ChangeType.CONSUME,
|
||||
).count(),
|
||||
1,
|
||||
)
|
||||
self.assertEqual(
|
||||
PointsLedger.objects.filter(
|
||||
ref_call=call,
|
||||
change_type=PointsLedger.ChangeType.REFUND,
|
||||
).count(),
|
||||
1,
|
||||
)
|
||||
|
||||
def test_image_upstream_timeout_refunds_precharged_points_and_marks_call_failed(self):
|
||||
self.provider.image_error = requests.Timeout("image upstream deadline exceeded")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user