fix(sector-radar): 支持当前上市股票资金流补拉
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import threading
|
||||
from datetime import date
|
||||
|
||||
import pytest
|
||||
@@ -87,6 +88,109 @@ def test_rate_limit_cooldown_is_shared_by_following_requests() -> None:
|
||||
assert waits == [60]
|
||||
|
||||
|
||||
def test_request_start_interval_allows_overlapping_provider_calls() -> None:
|
||||
current = [0.0]
|
||||
state_lock = threading.Lock()
|
||||
first_started = threading.Event()
|
||||
release_first = threading.Event()
|
||||
waits: list[float] = []
|
||||
starts: list[tuple[str, float]] = []
|
||||
errors: list[BaseException] = []
|
||||
|
||||
def clock() -> float:
|
||||
with state_lock:
|
||||
return current[0]
|
||||
|
||||
def wait(seconds: float) -> None:
|
||||
with state_lock:
|
||||
waits.append(seconds)
|
||||
current[0] += seconds
|
||||
|
||||
coordinator = RequestCoordinator(
|
||||
max_retries=0,
|
||||
request_interval_seconds=0.2,
|
||||
clock=clock,
|
||||
wait_fn=wait,
|
||||
sleep_fn=wait,
|
||||
)
|
||||
|
||||
def first_request() -> object:
|
||||
starts.append(("first", clock()))
|
||||
first_started.set()
|
||||
if not release_first.wait(timeout=2):
|
||||
raise AssertionError("first provider call was not released")
|
||||
return "first"
|
||||
|
||||
def run_first() -> None:
|
||||
try:
|
||||
coordinator.call("first", first_request)
|
||||
except BaseException as exc: # pragma: no cover - surfaced by the assertion below
|
||||
errors.append(exc)
|
||||
|
||||
first_thread = threading.Thread(target=run_first)
|
||||
first_thread.start()
|
||||
assert first_started.wait(timeout=2)
|
||||
|
||||
second = coordinator.call(
|
||||
"second",
|
||||
lambda: starts.append(("second", clock())) or "second",
|
||||
)
|
||||
|
||||
assert second == "second"
|
||||
assert first_thread.is_alive()
|
||||
release_first.set()
|
||||
first_thread.join(timeout=2)
|
||||
assert not first_thread.is_alive()
|
||||
assert errors == []
|
||||
assert starts == [("first", 0.0), ("second", 0.2)]
|
||||
assert waits == [0.2]
|
||||
|
||||
|
||||
def test_request_start_interval_is_disabled_by_default() -> None:
|
||||
waits: list[float] = []
|
||||
starts: list[str] = []
|
||||
coordinator = RequestCoordinator(
|
||||
max_retries=0,
|
||||
clock=lambda: 0.0,
|
||||
wait_fn=waits.append,
|
||||
)
|
||||
|
||||
coordinator.call("first", lambda: starts.append("first"))
|
||||
coordinator.call("second", lambda: starts.append("second"))
|
||||
|
||||
assert starts == ["first", "second"]
|
||||
assert waits == []
|
||||
|
||||
|
||||
def test_request_start_interval_applies_to_retry_attempts() -> None:
|
||||
current = [0.0]
|
||||
waits: list[float] = []
|
||||
starts: list[float] = []
|
||||
|
||||
def wait(seconds: float) -> None:
|
||||
waits.append(seconds)
|
||||
current[0] += seconds
|
||||
|
||||
coordinator = RequestCoordinator(
|
||||
max_retries=1,
|
||||
backoff_seconds=0,
|
||||
request_interval_seconds=0.2,
|
||||
clock=lambda: current[0],
|
||||
wait_fn=wait,
|
||||
sleep_fn=wait,
|
||||
)
|
||||
|
||||
def request() -> object:
|
||||
starts.append(current[0])
|
||||
if len(starts) == 1:
|
||||
raise RuntimeError("transient provider failure")
|
||||
return "ok"
|
||||
|
||||
assert coordinator.call("daily", request) == "ok"
|
||||
assert starts == [0.0, 0.2]
|
||||
assert waits == [0.0, 0.2]
|
||||
|
||||
|
||||
def test_pro_bar_qfq_calls_are_bound_to_the_shared_coordinator(
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
) -> None:
|
||||
|
||||
Reference in New Issue
Block a user