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
170
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
250
AWS Cloud Formation Git Syncで始める 頑張らない自動デプロイ
miyamo2
0
180
Other Decks in Programming
See All in Programming
過去最大のMCPアップデート! 2026-07-28 RC版の謎に迫る
licux
6
340
JJUG CCC 2026 Spring: JSpecify で実現する Kotlin フレンドリーな Java API 設計
ternbusty
1
170
Composerを使ったサプライチェーン攻撃の様子を眺めてみる #phpstudy
o0h
PRO
2
250
依存関係から依存物へ―Dependencyという言葉の歴史をひも解く
j_lee
0
120
Oxcを導入して開発体験が向上した話
yug1224
4
320
OSもどきOS
arkw
0
570
Webフレームワークの ベンチマークについて
yusukebe
0
170
エンジニアと一緒にテストコードの設計と実装を改善した話
mototakatsu
0
180
「AIで開発し、AIを届ける」をEvalでつなぐ 〜AIネイティブに始めるプロダクト開発の実践〜 / Connecting "Develop with AI, deliver AI" with Eval
rkaga
4
5.1k
Spring Security 実践 ─ GraphQL APIで実務に役立つ 認証・認可 を学ぶ
wagyu
0
240
Hunting Vulnerabilities in Symfony with LLMs
vinceamstoutz
0
540
net-httpのHTTP/2対応について
naruse
0
490
Featured
See All Featured
Build your cross-platform service in a week with App Engine
jlugia
234
18k
RailsConf 2023
tenderlove
30
1.5k
The Curious Case for Waylosing
cassininazir
1
390
Chasing Engaging Ingredients in Design
codingconduct
0
220
Skip the Path - Find Your Career Trail
mkilby
1
150
Code Review Best Practice
trishagee
74
20k
Primal Persuasion: How to Engage the Brain for Learning That Lasts
tmiket
0
370
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
16
2k
Digital Ethics as a Driver of Design Innovation
axbom
PRO
1
310
Joys of Absence: A Defence of Solitary Play
codingconduct
1
390
jQuery: Nuts, Bolts and Bling
dougneiner
66
8.5k
Large-scale JavaScript Application Architecture
addyosmani
515
110k
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