feat(system):优化后端
1.新增后端测试 2.增加了后端的加密 3.增加了i18n(国际化)
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
"""``retry_on_retryable_error`` 装饰器:覆盖同步/异步、重试次数、退避语义。"""
|
||||
|
||||
import asyncio
|
||||
|
||||
import pytest
|
||||
|
||||
from kilostar.utils.error import NonRetryableError, RetryableError
|
||||
from kilostar.utils.retry import retry_on_retryable_error
|
||||
|
||||
|
||||
def test_sync_retries_until_success(monkeypatch):
|
||||
sleep_calls: list[float] = []
|
||||
monkeypatch.setattr("time.sleep", lambda s: sleep_calls.append(s))
|
||||
|
||||
counter = {"n": 0}
|
||||
|
||||
@retry_on_retryable_error(max_retries=3, base_delay=1)
|
||||
def flaky() -> str:
|
||||
counter["n"] += 1
|
||||
if counter["n"] < 3:
|
||||
raise RetryableError("temp")
|
||||
return "ok"
|
||||
|
||||
assert flaky() == "ok"
|
||||
assert counter["n"] == 3
|
||||
# 第 1、2 次失败前各 sleep 一次:base * 2**0 = 1, base * 2**1 = 2
|
||||
assert sleep_calls == [1, 2]
|
||||
|
||||
|
||||
def test_sync_reraises_after_exhaustion(monkeypatch):
|
||||
monkeypatch.setattr("time.sleep", lambda _s: None)
|
||||
|
||||
@retry_on_retryable_error(max_retries=2, base_delay=1)
|
||||
def always_fail() -> None:
|
||||
raise RetryableError("nope")
|
||||
|
||||
with pytest.raises(RetryableError):
|
||||
always_fail()
|
||||
|
||||
|
||||
def test_sync_does_not_retry_on_non_retryable(monkeypatch):
|
||||
sleep_calls: list[float] = []
|
||||
monkeypatch.setattr("time.sleep", lambda s: sleep_calls.append(s))
|
||||
|
||||
@retry_on_retryable_error(max_retries=5, base_delay=1)
|
||||
def boom() -> None:
|
||||
raise NonRetryableError("hard")
|
||||
|
||||
with pytest.raises(NonRetryableError):
|
||||
boom()
|
||||
assert sleep_calls == []
|
||||
|
||||
|
||||
async def test_async_retries_until_success(monkeypatch):
|
||||
sleep_calls: list[float] = []
|
||||
|
||||
async def fake_sleep(s: float) -> None:
|
||||
sleep_calls.append(s)
|
||||
|
||||
monkeypatch.setattr(asyncio, "sleep", fake_sleep)
|
||||
|
||||
counter = {"n": 0}
|
||||
|
||||
@retry_on_retryable_error(max_retries=4, base_delay=2)
|
||||
async def flaky() -> int:
|
||||
counter["n"] += 1
|
||||
if counter["n"] < 2:
|
||||
raise RetryableError("temp")
|
||||
return 42
|
||||
|
||||
assert await flaky() == 42
|
||||
assert counter["n"] == 2
|
||||
assert sleep_calls == [2] # base * 2**0
|
||||
|
||||
|
||||
async def test_async_reraises_after_exhaustion(monkeypatch):
|
||||
async def fake_sleep(_s: float) -> None:
|
||||
return None
|
||||
|
||||
monkeypatch.setattr(asyncio, "sleep", fake_sleep)
|
||||
|
||||
@retry_on_retryable_error(max_retries=2, base_delay=1)
|
||||
async def boom() -> None:
|
||||
raise RetryableError("nope")
|
||||
|
||||
with pytest.raises(RetryableError):
|
||||
await boom()
|
||||
Reference in New Issue
Block a user