2026-10-27 23:42:15 -04:00
|
|
|
"""同一意图不可重复排队,重试必须保留原始批次和范围。"""
|
|
|
|
|
|
|
|
|
|
from uuid import uuid4
|
|
|
|
|
|
|
|
|
|
import pytest
|
|
|
|
|
from sqlalchemy import func, select
|
|
|
|
|
|
|
|
|
|
from app.core.exceptions import BadRequestError
|
|
|
|
|
from app.models import TPlusSyncBatch, TPlusSyncError
|
|
|
|
|
from app.schemas.tplus import TPlusCreateIn, TPlusRetryIn
|
|
|
|
|
from app.services.tplus import task_service
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _create(**kwargs):
|
|
|
|
|
return TPlusCreateIn(request_key=uuid4(), entity_types=["products"], **kwargs)
|
|
|
|
|
|
|
|
|
|
|
2026-11-02 22:20:55 -05:00
|
|
|
def test_关闭源读取仍禁止新建采集任务(tplus_session, monkeypatch):
|
|
|
|
|
from app.core.config import Settings
|
|
|
|
|
|
|
|
|
|
settings = Settings(_env_file=None, app_secret_key="x" * 32)
|
|
|
|
|
monkeypatch.setattr(task_service, "get_settings", lambda: settings)
|
|
|
|
|
with pytest.raises(BadRequestError, match="未启用"):
|
|
|
|
|
task_service.create_task(tplus_session, _create())
|
|
|
|
|
assert tplus_session.scalar(select(func.count()).select_from(TPlusSyncBatch)) == 0
|
|
|
|
|
|
|
|
|
|
|
2026-10-27 23:42:15 -04:00
|
|
|
def test_同键同意图复用同一批次(tplus_session):
|
|
|
|
|
request = _create()
|
|
|
|
|
first = task_service.create_task(tplus_session, request)
|
|
|
|
|
second = task_service.create_task(tplus_session, request)
|
|
|
|
|
assert first.id == second.id
|
|
|
|
|
assert first.status == "QUEUED"
|
|
|
|
|
assert first.started_at is None
|
|
|
|
|
assert first.entity_types_json == ["products"]
|
|
|
|
|
assert tplus_session.scalar(select(func.count()).select_from(TPlusSyncBatch)) == 1
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_同键不同范围拒绝(tplus_session):
|
|
|
|
|
request = _create()
|
|
|
|
|
task_service.create_task(tplus_session, request)
|
|
|
|
|
changed = TPlusCreateIn(request_key=request.request_key, entity_types=["personnel"])
|
|
|
|
|
with pytest.raises(BadRequestError, match="幂等"):
|
|
|
|
|
task_service.create_task(tplus_session, changed)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_失败重试创建新批次并保留原错误(tplus_session):
|
|
|
|
|
parent = task_service.create_task(tplus_session, _create())
|
|
|
|
|
parent.status = "FAILED"
|
|
|
|
|
tplus_session.add(
|
|
|
|
|
TPlusSyncError(
|
|
|
|
|
batch_no=parent.batch_no,
|
|
|
|
|
entity_type="products",
|
|
|
|
|
source_table="AA_Inventory",
|
|
|
|
|
error_code="READ_ERROR",
|
|
|
|
|
error_message="读取失败",
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
tplus_session.commit()
|
|
|
|
|
retry = TPlusRetryIn(request_key=uuid4())
|
|
|
|
|
child = task_service.retry_task(tplus_session, parent.batch_no, retry)
|
|
|
|
|
replay = task_service.retry_task(tplus_session, parent.batch_no, retry)
|
|
|
|
|
assert child.id == replay.id and child.id != parent.id
|
|
|
|
|
assert child.parent_batch_no == parent.batch_no
|
|
|
|
|
assert parent.status == "FAILED"
|
|
|
|
|
assert tplus_session.scalar(select(TPlusSyncError.retry_count)) == 1
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_已有未完成重试时不重复排队(tplus_session):
|
|
|
|
|
parent = task_service.create_task(tplus_session, _create())
|
|
|
|
|
parent.status = "FAILED"
|
|
|
|
|
tplus_session.commit()
|
|
|
|
|
task_service.retry_task(tplus_session, parent.batch_no, TPlusRetryIn(request_key=uuid4()))
|
|
|
|
|
with pytest.raises(BadRequestError, match="重试任务"):
|
|
|
|
|
task_service.retry_task(tplus_session, parent.batch_no, TPlusRetryIn(request_key=uuid4()))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_成功或未知历史范围不能自动重试(tplus_session):
|
|
|
|
|
parent = task_service.create_task(tplus_session, _create())
|
|
|
|
|
parent.status = "SUCCEEDED"
|
|
|
|
|
tplus_session.commit()
|
|
|
|
|
with pytest.raises(BadRequestError):
|
|
|
|
|
task_service.retry_task(tplus_session, parent.batch_no, TPlusRetryIn(request_key=uuid4()))
|
|
|
|
|
parent.status, parent.entity_types_json = "FAILED", None
|
|
|
|
|
tplus_session.commit()
|
|
|
|
|
with pytest.raises(BadRequestError, match="范围"):
|
|
|
|
|
task_service.retry_task(tplus_session, parent.batch_no, TPlusRetryIn(request_key=uuid4()))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_关联核验不需要读取实体范围(tplus_session):
|
|
|
|
|
batch = task_service.create_task(
|
|
|
|
|
tplus_session, TPlusCreateIn(task_type="AUDIT", request_key=uuid4())
|
|
|
|
|
)
|
|
|
|
|
assert batch.sync_mode == "AUDIT"
|
|
|
|
|
assert batch.entity_types_json == []
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_预留增量批次不得静默改为全量重试(tplus_session):
|
|
|
|
|
batch = task_service.create_task(tplus_session, _create())
|
|
|
|
|
batch.status, batch.sync_mode = "FAILED", "INCREMENTAL"
|
|
|
|
|
tplus_session.commit()
|
|
|
|
|
with pytest.raises(BadRequestError, match="方式"):
|
|
|
|
|
task_service.retry_task(tplus_session, batch.batch_no, TPlusRetryIn(request_key=uuid4()))
|