Retry-After is never read on 429 retries: dict(httpx.Headers) lowercases the key
まだ誰も着手していません。
評価
- 難易度
- 2/5
- 見積もり時間
- 1〜3時間
- 初心者へのやさしさ
- 78/100
調査の方向性
まず shopify_app/graphql/admin_graphql.py の 111 行目と 708 行目から確認し、次に 389 行目と 445 行目の sync および async の 429 ハンドラーを調べてください。提供された httpx スニペットを使ってヘッダーキーの動作を再現し、両方の retry パスがデフォルト値ではなくサーバーが提供する Retry-After 値を使用していることを確認してください。
索引モデルが issue の本文から書いたものです。
説明
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.
- 主要言語
- Python
- スター
- 17
- フォーク
- 1
- 平均マージ
- 3分
- マージ済み PR(30日)
- 2
コントリビューションガイド
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
Shopify/shopify-app-python のほかの issue
-
devtools-gardener
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
Shopify/shopify-app-python の issue をすべて見る
似ている issue
-
triage/confirmed
難易度 2/5 1〜3時間 初心者へのやさしさ 88/100
agentscope-ai/agentscope#2775 ·
-
comp/desktop P3 type/bug
難易度 1/5 1時間未満 初心者へのやさしさ 92/100
NousResearch/hermes-agent#118866 ·
-
bug
難易度 1/5 1時間未満 初心者へのやさしさ 90/100
apache/cloudstack#14222 ·
-
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
-
bug
難易度 2/5 1〜3時間 初心者へのやさしさ 82/100