Retry-After is never read on 429 retries: dict(httpx.Headers) lowercases the key
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 2/5
- Thời gian dự kiến
- 1-3 giờ
- Mức phù hợp với người mới
- 78/100
Hướng nghiên cứu
Bắt đầu với shopify_app/graphql/admin_graphql.py tại các dòng 111 và 708, sau đó kiểm tra các handler 429 sync và async tại các dòng 389 và 445. Tái hiện hành vi của khóa header bằng snippet httpx được cung cấp và xác nhận rằng cả hai đường dẫn retry đều sử dụng giá trị Retry-After do máy chủ cung cấp thay vì giá trị mặc định.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Summary
In admin_graphql_request, the Retry-After header is never read on a 429 response. The lookup always falls through to its "1" default, so every rate-limit retry sleeps exactly one second regardless of what the server asked for.
Affects both the sync and async paths.
Version: shopifyapp 1.0.1 (sdist from PyPI), httpx 0.28.1.
Cause
shopify_app/graphql/admin_graphql.py:111 (and :708 on the async path) normalizes the response headers with:
response_headers = dict(response.headers)
dict() on an httpx.Headers instance produces lowercased keys. The 429 handlers then look the header up with its canonical casing, at shopify_app/graphql/admin_graphql.py:389 (sync) and :445 (async):
retry_after = response_headers.get("Retry-After", "1")
That key is never present, so retry_after is always the literal string "1".
Reproduction
import httpx
h = httpx.Headers({"Retry-After": "2.0", "Content-Type": "application/json"})
d = dict(h)
print(list(d)) # ['retry-after', 'content-type']
print(d.get("Retry-After", "1")) # '1' <- expected '2.0'
Impact
The client ignores server-provided backoff on rate limiting and retries on a fixed one-second interval instead. With the default max_retries=2 that is about two seconds of total backoff, typically well short of what a rate-limited endpoint asks for.
Suggested fix
httpx.Headers is already case-insensitive, so reading from the response object directly avoids the problem:
retry_after = response.headers.get("Retry-After", "1")
Keeping the dict and looking up the lowercase key works too.
One caveat: fixing this lookup on its own exposes a second defect on the same value, where int(retry_after) raises ValueError on anything that is not a bare integer. Filed separately as #18, which also notes that the two are best addressed together.
- Ngôn ngữ chính
- Python
- Star
- 17
- Fork
- 1
- Merge trung bình
- 4 phút
- Pull request đã merge (30 ngày)
- 1
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của Shopify/shopify-app-python
-
int(retry_after) raises ValueError on a non-integer Retry-After valueCó thể làm lại được Pull request cho issue này đã bị đóng mà không được merge. Đang mởdevtools-gardener
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
Tất cả issue của Shopify/shopify-app-python
Issue tương tự
-
bug needs-triage
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
debpalash/VoiceStudio#2624 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 75/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
-
Make Catch2 optional when `RDK_BUILD_CPP_TESTS=OFF`Có thể đã có người làm @pechersky đã nhận hôm nay. Đang mởbug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
Maintainer thường phản hồi trong vòng 2 ngày
-
There are a few redundant calls to `fdesc._setCloseOnExec()`Có thể đã có người làm @gudnimg đã nhận hôm nay. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
Maintainer thường phản hồi trong vòng 1 ngày