ルートが存在しないentity groupのトランザクション処理に関するmore low levelからの考察

ルートエンティティが存在しなくてもエンティティグループに対するトランザクション処理が正常に行われる。つまり、トランザクション管理で使用されるエンティティグループのタイムスタンプは、Datastoreのエンティティとは関係が無いところで管理されている可能性がある

@shin1ogawaさんのブログより。


この現象、結構気になっていました。

@ashigeruさんと@shin1ogawaさんが当該事象について検証されていて、@shin1ogawaさんのコードがgitbubに置いてあったのをめざとく見つけたので、ちょっとばかり考察してみます。

まず、僕はmore low levelerなので、putのときのprotocol bufferのデータ構造を見てみることにしました。オブジェクト図を書くと、こんな感じです。

PutRequstはputするときにdatastoreとの通信に使用されているであろうクラスです。こいつがトランザクションを持っています。
EntityProtoがエンティティの実体ですね。こいつはエンティティグループと思われるPathとエンティティのプロパティを持っています。
Pathは、おそらくエンティティグループそのものです。エンティティグループとなるkind群を保持しています。

※前提条件として、setはone to one対応、addはone to many対応であるものとしてお絵描きしています。メソッド名からの推定がすべて正しいものとして考えている、と見てください。

ここから先は若干の推測が入りますが、
・allocateIdsを指定してkeyを取得するケースにおいては、既にエンティティグループの関連として必要なPathオブジェクト構造は成立しており、親エンティティの永続状態に関わらず子は親を認識している

まさに、keyによるエンティティグループの関係が構築されており、kindとidに対する参照ではなく、各エンティティが保持するエンティティグループのkindとkeyの値によってエンティティグループの関連が構築されていると。

・また、transactionありでのputを行うケースに置いては、取得されたtransactionのhandleでbigtable(またはdatastore)での楽観ロック制御が行われるため、親エンティティの永続状態にtransaction制御は依存していない
keyの取得時点で値がコピーされエンティティグループが成立しているのであれば、トランザクションが効くのは自然なことと思います。

また、トランザクション制御の単位はエンティティグループではなく、サービス呼び出しのprotocol bufferを単位としている、ということも見て取れます。


また、トランザクション制御がprotocol bufferのオブジェクトを単位としているというのも、素直な結論です。

グルージェントさんの書籍 140pにも、

操作対象は単一のノード上に存在しなければならないため、エンティティグループというしくみを利用して複数のエンティティを同一のノード上に配置します。

とあり、サービス呼び出しがトランザクション制御の単位になっているという僕の推定とも整合します。


よって、いずれのputも、allocateIdsやcreateKeyが発行された時点で値としてエンティティグループが構成されており、トランザクション制御が成立することになります。


ということじゃないかなーと。
仕組み的に永続化層をスケールアウト可能にするとしたら、個人的には納得がいく結論でした。