emahiro/b.log

Drastically Repeat Yourself !!!!

DynamoDB のリクエストで Context Canceled をハンドリングする

Overview

タイトルの通りです。 DynamoDB へのリクエストにおいて Context Cancel エラーになった場合にその Context Cancel をハンドリングします。

DynamoDB 側でのエラーハンドリング

DynamoDB へのリクエストにおいて Context Cancel の実装は https://pkg.go.dev/github.com/aws/smithy-go#CanceledError.CanceledError でされています。

CanceledError returns true to satisfy interfaces checking for canceled errors.

Godoc にも canceled の時に返されると記載されているので、最終的にこの Context cancel エラーをハンドリングしたい箇所で取り出してハンドリングできれば良さそうです。

コードを追っかけていきます

実際に SDK のコードを追っていきます。

Query() 関数をサンプルとして見ていきます。

Query 関数の内部で invokeOperation を 呼び出していて、この invokeOperation の中での smithy-go 内部にある middleware.DecorateHandlerHandle メソッドを Call します。このい Handle メソッドで発生してエラーは invokeOperation メソッドでは OperationError として返されます。 Handle メソッドのエラーが OperationError に入れられて返されることになります。

次にこの Handle の実装以下を追っていきます。

この Handle メソッド内部で Middleware に実装された HandleMiddleware を Call しており、これは BuildStep に実装されたHandleMiddleware を Callします。
さらに、この実装の内部で buildWrapHandler が実装してる HandleBuild を Call しており、HandleBuild 内部の buildWrapHandler.Handler に実装されている Handle メソッドで実際に AWS 本体と通信してる HTTP Client に実装された Handle メソッド の内部で、smithy-go.CanceledError返してる箇所があります。

これがエラーを返してる本体です。

実際のエラーハンドリング方法

いくつかやり方があると思います。一番単純なのは Dynamo から返されたエラーの文字列の中に context canceled が含まれていればヨシ!とする方法です。
ただし、エラーの文字列一致はそれじゃないと対応できない場合を除いて極力採用するべき方針ではありません。

できることであれば Go のエラー方をそのまま使って errors.Is でハンドリングしたいです。Go のエラーはエラーが返される過程で fmt で wrap されている or 独自エラーで wrap されている限り errors.Is でエラーの判別をすることが可能です。

※ どこかでエラーを書き換えてしまってる場合、正常にハンドリングできません。

実際にエラーが取り出せるかをキャストでやって見ました -> https://play.golang.org/p/KPPzJgqspIk
これは trueが返ってきました(つまり context canceled が発火したということ)

次に errors.Is でハンドリングできるかやって見ました -> https://play.golang.org/p/vT4anMduCL7
※ 余計なエラーで書き換えてない場合のみ。途中に errors.New があったりして元々のエラーからさらに書き換えていると Is で取り出すことはできません。

まとめ

エラーハンドリング、、されどエラーハンドリング。
安易に文字列比較に逃げることなく、Error が定義されてるはずだ、と見通しを立てて実装するって大事だなと思いました。

追記

AWS のリクエストを送信する invokeOperation メソッドが返す smithy.OperationErrorUnwrap実装してる ので、AWS 内では発生した何かしらの OperationErrorerrors.IsUnwrap して取り出すのが良いです。

OperationErroroperation error {$ResourceName}: {$OperationName}, https response error... という文字列で返ってくるエラーのことです。