Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Httpリクエストを自動リトライ・ポーリングするイテレータを作ってみた
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
miyamo2
September 04, 2024
Programming
200
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Httpリクエストを自動リトライ・ポーリングするイテレータを作ってみた
2024/09/04 Go Connect #2
https://gotalk.connpass.com/event/327544/
miyamo2
September 04, 2024
More Decks by miyamo2
See All by miyamo2
Go 1.24 tool directiveは何を変えるのか
miyamo2
1
270
AWS Cloud Formation Git Syncで始める 頑張らない自動デプロイ
miyamo2
0
190
Other Decks in Programming
See All in Programming
FDEとは、何者なのか?
masapyon1212
0
120
[DroidKaigi 26] How We Moved from Android Studio to Slack
thisaay
0
170
承認済みなのに差戻しできてしまうバグ、型で潰せます
shinchit
0
130
リアルな遅延を測る仕様
kota_yata
1
140
AIの中の人になってみる
htkym
0
150
PyO3 で既存 Python 評価器を Rust core 化する ー wasm-bindgen でブラウザにも配るための設計
kdash
1
310
まずはプロンプトガイドを読もう、話はそれからだ
kiakiraki
1
250
関東Kaggler会_NVIDIA_Nemotron_コンペ_振り返り
rick_ds
0
800
AI駆動開発にグラフDBを重ねてみた
satoshi256kbyte
2
700
AIと壁打ちしながら進めるコスト管理
fufuhu
2
1.9k
【DroidKaigi 2026】「アクセシビリティを利用するとき、 アクセシビリティもまたこちらを利用している」 〜マルウェアによる攻撃と防衛について〜
halunoyo
0
270
Can LLMs Replicate 4 Years of Compose Migration? Exploring the boundaries of automation with 279 XML files from a real product
makun
0
130
Featured
See All Featured
Optimizing for Happiness
mojombo
378
71k
Leading Effective Engineering Teams in the AI Era
addyosmani
9
2.5k
What does AI have to do with Human Rights?
axbom
PRO
1
2.4k
Music & Morning Musume
bryan
47
7.4k
Money Talks: Using Revenue to Get Sh*t Done
nikkihalliwell
0
490
GraphQLの誤解/rethinking-graphql
sonatard
75
12k
Applied NLP in the Age of Generative AI
inesmontani
PRO
4
2.4k
Embracing the Ebb and Flow
colly
88
5.2k
svc-hook: hooking system calls on ARM64 by binary rewriting
retrage
2
550
Amusing Abliteration
ianozsvald
1
280
Designing for Timeless Needs
cassininazir
1
470
Bootstrapping a Software Product
garrettdimon
PRO
306
120k
Transcript
Httpリクエストを自動リトライ・ポーリングす るイテレータを作ってみた 2024/09/04 Go Connect #2 @miyamo2
話すこと・話さないこと 話すこと 作ったものの概要とその使い方 話さないこと イテレータの概要や実装方法 作ったパッケージの内部実装について
作ったもの できること ステータスコードに応じた自動リトライ レスポンスボディとエラーに応じた自動リトライ(ポーリング処理) 上記の結果のイテレーション
サンプルコード url := "http://example.com" ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) defer
cancel() opts := []r2.Option{ r2.WithMaxRequestAttempts(3), r2.WithPeriod(time.Second), } for resp, err := range r2.Get(ctx, url, opts...) { if err != nil { slog.WarnContext(ctx, "something happened.", slog.Any("error", err)) // Note: continueを使用してもイテレータが終了する場合がある continue } if resp == nil { slog.WarnContext(ctx, "response is nil") continue } if resp.StatusCode != http.StatusOK { slog.WarnContext(ctx, "unexpected status code.", slog.Int("expect", http.StatusOK), slog.Int("got", resp.StatusCode)) continue } buf, err := io.ReadAll(resp.Body) if err != nil { slog.ErrorContext(ctx, "failed to read response body.", slog.Any("error", err)) continue } slog.InfoContext(ctx, "response", slog.String("response", string(buf))) // r2ではデフォルトでリクエストボディが自動クローズするため明示的にクローズ処理を行う必要がない }
r2がイテレータを終了する条件 リクエストが成功(ステータスコードが200 ~ 399)、 かつ WithTerminateIf が指定されていない場合 WithTerminateIf で指定された条件が満たされた場合 429:
Too Many Requests以外の4xx クライアントエラーが返された 場合 WithMaxRequestAttempts によって指定されたリクエストの最大回数 を超えた場合 引数で渡された context.Context がキャンセルされた場合 for rangeループがbreakによって中断された場合
Get 以外にr2で用意されている関数 func Head(ctx context.Context, url string, options ...Option) (*http.Response,
error) func Post(ctx context.Context, url string, body io.Reader, options ...Option) (*http.Response, error) func Put(ctx context.Context, url string, body io.Reader, options ...Option) (*http.Response, error) func Patch(ctx context.Context, url string, body io.Reader, options ...Option) (*http.Response, error) func Delete(ctx context.Context, url string, body io.Reader, options ...Option) (*http.Response, error) func PostForm(ctx context.Context, url string, data url.Values, options ...Option) (*http.Response, error)
r2で用意されているオプション WithMaxRequestAttempts WithPeriod WithInterval WithTerminateIf WithHttpClient WithHeader WithContentType WithAspect WithAutoCloseResponseBody
r2で用意されているオプション WithMaxRequestAttempts WithPeriod WithInterval WithTerminateIf WithHttpClient WithHeader WithContentType WithAspect WithAutoCloseResponseBody
WithMaxRequestAttempts func WithMaxRequestAttempts(maxRequestTimes int) Option r2.WithMaxRequestAttempts(3) リクエストの最大回数を指定する デフォルト、もしくは0が設定された場合は回数無制限でリクエスト を行う リトライではなく、リクエストの回数を指定するオプションなので注
意
WithPeriod func WithPeriod(period time.Duration) Option r2.WithPeriod(time.Second) 各リクエストのタイムアウト時間を指定する デフォルト、もしくは0が設定された場合はタイムアウトしない http.Client.Timeout を使用せず
r2 独自で context.WithTimeout を用い たハンドリングを行う http.Client.Timeout と併用して同じ値が設定された場合にどちらのタ イムアウトが適用されるかの動作は未定義
WithInterval func WithInterval(interval time.Duration) Option r2.WithInterval(time.Second) 各リクエストの間隔を指定する デフォルト、もしくは0が設定された場合は以下のどちらかで算出さ れる Backoff
And Jitterアルゴリズム 'Retry-After'ヘッダーを参照 (Too Many Requestsが返された場合に限り)
WithTerminateIf func WithTerminateIf(terminationCondition func(resp *http.Response, err error) bool) Option r2.WithTerminateIf(
func(resp *http.Response, _ error) bool { buf, err := io.ReadAll(resp.Body) if err != nil { return true } data := map[string]any{} if err := json.Unmarshal(buf, data); err != nil { return false } return data["foo"] == "bar" }) ユーザー独自の終了条件を指定する レスポンスボディの巻き戻しは r2 側で対応
WithAutoCloseResponseBody func WithAutoCloseResponseBody(autoCloseResponseBody bool) Option r2.WithAutoCloseResponseBody(false) リクエストボディを r2 側で自動でクローズする デフォルト、もしくはtrueが設定された場合は有効
参考 イテレータによってGoはどう変わるのか https://audience.ahaslides.com/cl965inb88/review?lookback-tab=slides Go の iter パッケージを使ってみよう https://zenn.dev/mattn/articles/641f1d86fffdc9 Goのリトライ処理で考慮すること https://zenn.dev/imamura_sh/articles/retry-46aa586aeb5c3c28244e
mattn/go-for-range-experiment-example https://github.com/mattn/go-for-range-experiment-example avast/retry-go https://github.com/avast/retry-go