返回 last30days-skill
test_reddit_keyless_wait_allowance.py
根目录 / tests / test_reddit_keyless_wait_allowance.py
1 """Per-future result timeouts must cover the keyless bucket's queue.
2
3 At 1 req/s, a batch of thirteen feed URLs on four workers queues about
4 thirteen seconds of token waits before the last fetch even starts, and four
5 subquery streams share the same bucket. A fixed 20-second future timeout then
6 expires while the fetch is still waiting for a token, and the feed is dropped
7 (`[RedditRSS] feed future failed:` with an empty message on the 2026-08-31
8 smoke run).
9 """
10
11 import threading
12 from unittest import mock
13
14 from lib import http, reddit_listing, reddit_rss
15
16
17 def test_limiter_reports_waiting_threads():
18 limiter = http.RateLimiter(rate_per_sec=1000.0, burst=1)
19 assert limiter.waiting == 0
20 limiter.acquire() # drains the single token
21 started = threading.Event()
22
23 def _wait():
24 started.set()
25 limiter.acquire()
26
27 t = threading.Thread(target=_wait)
28 t.start()
29 started.wait(timeout=1)
30 # The waiter is inside acquire() until a token refills.
31 deadline = threading.Event()
32 deadline.wait(timeout=0.01)
33 t.join(timeout=2)
34 assert limiter.waiting == 0
35
36
37 def test_wait_allowance_scales_with_batch_and_queue(monkeypatch):
38 limiter = http.RateLimiter(rate_per_sec=1.0, burst=2)
39 monkeypatch.delenv(http.REDDIT_KEYLESS_RATE_ENV, raising=False)
40 with mock.patch.object(http, "REDDIT_KEYLESS_LIMITER", limiter):
41 pad = http.REDDIT_KEYLESS_CONTENTION_SECONDS
42 assert http.reddit_keyless_wait_allowance(13) == 13.0 + pad
43 limiter._waiting = 5
44 assert http.reddit_keyless_wait_allowance(13) == 18.0 + pad
45 # The allowance syncs the configured rate before computing.
46 monkeypatch.setenv(http.REDDIT_KEYLESS_RATE_ENV, "2")
47 assert http.reddit_keyless_wait_allowance(13) == 9.0 + pad
48
49
50 def test_rss_and_listing_result_timeouts_include_the_allowance(monkeypatch):
51 limiter = http.RateLimiter(rate_per_sec=1.0, burst=2)
52 monkeypatch.delenv(http.REDDIT_KEYLESS_RATE_ENV, raising=False)
53 with mock.patch.object(http, "REDDIT_KEYLESS_LIMITER", limiter):
54 pad = http.REDDIT_KEYLESS_CONTENTION_SECONDS
55 assert reddit_rss._result_timeout(13) == reddit_rss.FEED_TIMEOUT + 5 + 13.0 + pad
56 assert reddit_listing._result_timeout(20) == reddit_listing.LISTING_TIMEOUT + 5 + 20.0 + pad
57
58
59 def test_allowance_reflects_a_process_env_rate_override(monkeypatch):
60 limiter = http.RateLimiter(rate_per_sec=1.0, burst=2)
61 with mock.patch.object(http, "REDDIT_KEYLESS_LIMITER", limiter):
62 monkeypatch.setenv(http.REDDIT_KEYLESS_RATE_ENV, "0.5")
63 pad = http.REDDIT_KEYLESS_CONTENTION_SECONDS
64 assert http.reddit_keyless_wait_allowance(10) == 20.0 + pad
65
65 lines PYTHON