Datastore/Go の cannot load field xxxx into a xxx: no such struct field は Goon で回避できる

以下のブログに書いてある通り、
pospome.hatenablog.com

Datastore は kind の property が struct の field に存在しないと
ErrFieldMismatch というエラーが発生する。

「datastore: cannot load field xxxx into a xxx: no such struct field」のエラーと説明した方が分かりやすいかもしれない。
Datastore を使ったことのある人なら1回は見たことあるはず・・・。

エラーは発生するものの、
存在する filed に対応する property の値は struct へマッピングされるので、
datastore.ErrFieldMismatch をハンドリングして握りつぶしてしまえば、
Datastore の property と struct の field のミスマッチを気にせず処理を続けることができる。
でも、わざわざハンドリングするのはちょっと面倒くさい。

と思っていたが、
Goon は以下の PR が merge されたことで datastore.ErrFieldMismatch を回避することができる。
github.com

デフォルトで回避するようになっているので、
バージョンを上げれば面倒なエラーハンドリングからも開放される。
https://godoc.org/github.com/mjibson/goon#pkg-variables

// IgnoreFieldMismatch decides whether *datastore.ErrFieldMismatch errors
// should be silently ignored. This allows you to easily remove fields from structs.
IgnoreFieldMismatch = true

GAE/Go TaskQueue の max_doublings について

なんかググってもあんまり出てこなかったので、自分用メモ。

TaskQueue のリトライは queue.yaml で設定する。

以下のように設定すると、

task_retry_limit: 5
min_backoff_seconds: 10
max_backoff_seconds: 40

リトライ間隔は 10s -> 20s -> 30s -> 40s -> 40s のようになり、合計で5回リトライする。
min_backoff_seconds で設定した値が待機秒数に加算されるが、
最大でも max_backoff_seconds までしか増えない。
なので、5 回目は 50s になることなく、40s でリトライしている。

【追記】
上記の挙動は間違っていました。
max_doublings を指定しない場合は
10s -> 20s -> 40s -> 40s -> 40s
ように常に加算される待機秒数を2倍にして動作します。

待機秒数を大きく設定した場合、
待機秒数が2倍になっていくと値が大きくなりすぎて都合が悪いことがあるので、
max_doublings で制御する感じなんだと思います。
【追記終わり】

max_doublings では「加算される待機秒数を2倍にする回数」を設定することができる。

例えば、以下のように max_doublings = 3 に設定すると、

task_retry_limit: 7
min_backoff_seconds: 10
max_backoff_seconds: 500
max_doublings: 3

10s -> 20s -> 40s -> 80s -> 160s -> 240s -> 320s のように7回リトライする。

max_doublings = 3 によって、
最初の3回だけ待機秒数が2倍で増えるので、
4回目のリトライ間隔は 80s になる。
それ以降は2倍にならず、直近のリトライ間隔である 80s を加算していき、
最後の7回目のリトライでは 320s になる。

これは Exponential backoff というアルゴリズムらしい。
http://yoshidashingo.hatenablog.com/entry/2014/08/17/135017

GAE/Go の cron を毎時同じ時刻に起動させるための synchronized の設定

ちょっとハマったので書いておく。
結論から言うと、synchronized を設定すればいい。

GAE の cron は yaml で設定する。
https://cloud.google.com/appengine/docs/standard/go/config/cronref

今回は「30分ごとに起動する」という設定をしたかったので、以下のように書いた。

every 30 minutes

こう書けば、 00:00 -> 00:30 -> 01:00 のように30分おきに実行されるはずなのだが、
実行されない。

30分間隔で起動するだけで、
00:00 -> 00:30 -> 01:00 のように毎時30分間隔で起動してくれるわけではなかった。

例えば、00:10 にGCP コンソール上で手動で cron を起動すると、
次に起動するのは30分後の 00:40 になってしまう。

00:00 -> 00:30 -> 01:00 のように毎時30分間隔で起動するには
synchronized を設定する必要がある。

every 30 minutes synchronized

https://cloud.google.com/appengine/docs/standard/go/config/cronref#schedule_format

これで00:00 -> 00:30 -> 01:00 のように毎時30分間隔で起動するようになる。
00:10 にGCP コンソール上で手動で cron を起動したとしても、
次は 00:30 に起動してくれる。

ちなみに、from を設定すれば、特定の時間範囲も設定できる。

every 2 hours from 10:00 to 14:00

どこに何を書くのか?

これのLT資料。


kaizen.connpass.com

Twitter の反応









感想

もっと特定のケースに特化したやつの方が面白かったかな・・・。

アプリケーションコードにおける技術的負債について考える

社内勉強会資料