golang/go へ PR したよ

コメントの修正なのでたいした変更でもないのだけど、記念に記事を書いておく

github.com

github.com

net/httpTimeoutHandler 周りを眺めているとこの記述に引っかかった。

TimeoutHandler supports the Flusher and Pusher interfaces but does not support the Hijacker interface.

以前、 TimeoutHandler を使いつつ、少しでも速くクライアントへレスポンスを返したくて、先にレスポンスを返してそのあとログを書いたり後処理をするというコードを書こうとして、このあたりを調べた記憶があった。へーこの前はできなかったのにできるようになったのか、と思って眺めたものの Flush() メソッドが見つからない。ちょっとコードを書いて type assertion してみても ok ではない。

git log -p src/net/http/server.go を読んでいく

github.com

この revert のきっかけになった issue にあるように、Flush() すると単に TimeoutHandler のラップしている ResponseWriterFlush() を呼ぶだけで、設定したステータスコードは無視されるし、タイムアウトしても 503 が書かれない(response.WriteHeader が複数回呼ばれた警告が出る)。

しかも TimeoutHandler は内部でバッファを持っていて ServeHTTP の終了を待って ResponseWriter にコピーする実装なので、Flush() を呼んでも期待するようにクライアントへレスポンスが Flush されるわけではない。Header と Body はひと組で扱うものなのに、Flush() 呼べたら Flush するという従来の挙動は乱暴だしいかにもうまくいかなそう。 https://github.com/golang/go/blob/go1.13.3/src/net/http/server.go#L3237

ということで、TimeoutHandler.Flush() は revert されてしまったけど、コメントはそのまま残っていた。

PR 作る

すわプルリクチャンス、コメントなおすだけで golangリポジトリに名前載せられるぞと思ってトライした。

golang.org

Contribution Guide を読んで言う通りにする。
Google アカウントで Contributor License Agreement に同意したり、Gerrit にアカウントを作る。Gerrit よくわからないので、普段親しんでいる Github で PR を作って送る。

とにかくレビューしやすいように、ISSUE_TEMPLATE を埋めながら、上に挙げたようなタイムラインを示して、Playground に再現コードを書いて、issue を立てる。コミットログを漁って空気を読んだコミットメッセージを書いて、Fork したリポジトリへコミットして Pull-Request を作っておくる。PR のテンプレートにもいろいろドキュメントがあるのでそのとおりにする。同名のリポジトリの issue を参照する場合、Fixes golang#35161 のように {user_or_org}#{issue_num} で参照できるの知らなかった。

PR を送ったらあとは bot が Gerrit へ同期してくれる。https://go-review.googlesource.com/c/go/+/203478/

特に指摘もなく、寝ているうちにマージされていた。めでたしめでたし。

従来は Gerrit のワークフローで敷居が高かったけど、Github になってだいぶ簡単になったみたい。Contribution Guide にあるように、マージされると間のコミットは squash され、Pull-Request の Title と Description が最終的な1つのコミットメッセージになる。