Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Httpリクエストを自動リトライ・ポーリングするイテレータを作ってみた
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
miyamo2
September 04, 2024
Programming
210
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
UPDATE をやめる — EF Core でマスタをバージョン管理する
panda728
PRO
0
610
TiDB Cloudのカスタムコントローラーによるオートスケール対応
takaidohigasi
0
130
更なる可用性を求めて、5年間運用したKotlinのアプリケーションをGoでリプレイスする話
ken_tunc
0
360
AgentCore CLI で進化した AWS での AI エージェントの作り方 : 必要な機能を必要な時に
icoxfog417
PRO
3
380
『寄り添うラジオ』をAIで作る 体験価値から逆算した、会話しないUXと品質設計
theoriatec2024
3
190
仕様駆動開発による爆速プロダクト開発 / Bakusoku Spec Driven Development
kobakei
0
130
標準パッケージに uuid が追加された 背景から見る Go らしい意思決定 / go_127_uuid_decision
convto
5
8.4k
Security issues being discussed on Web Platforms
petamoriken
0
1.2k
Ghostty + Neovimで作る 透明でカッコ良い開発環境
j341nono
0
120
JRuby: Past, Present, and Future
headius
0
190
Webの地図
yosuke_furukawa
PRO
6
4.7k
The Rails Doctrine Decade
koic
2
380
Featured
See All Featured
The Hidden Cost of Media on the Web [PixelPalooza 2025]
tammyeverts
2
500
The Art of Programming - Codeland 2020
erikaheidi
57
14k
Building the Perfect Custom Keyboard
takai
2
880
brightonSEO & MeasureFest 2025 - Christian Goodrich - Winning strategies for Black Friday CRO & PPC
cargoodrich
3
850
Facilitating Awesome Meetings
lara
57
7.1k
16th Malabo Montpellier Forum Presentation
akademiya2063
PRO
0
390
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
17k
Designing for Performance
lara
611
70k
What's in a price? How to price your products and services
michaelherold
247
13k
The State of eCommerce SEO: How to Win in Today's Products SERPs - #SEOweek
aleyda
2
12k
Agile Actions for Facilitating Distributed Teams - ADO2019
mkilby
0
280
Ruling the World: When Life Gets Gamed
codingconduct
0
360
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