Amazon SimpleDBのConsistentReadを指定してみる

SimpleRecordというSimpleDB専用のActiveRecordクローンを試しているときに登録したはずのデータが取得できない現象が頻発しました。

POSTでデータ登録 -> Redirect GETで登録したデータを取得して表示しようとしたら、データが取得できてない!という流れです。

これはEventually Consistentが働いている現象なんだなーと思いました。(取得するデータが最新の状態である保証がない)

SimpleDBは今年の2月に取得するデータが最新の状態であることを保証するオプション「ConsistentRead」が追加されていました。

が、SimpleRecordもその中で使われているawsもConsistentReadは未対応のようです。
なので無理矢理ConsistentReadを使うように変えてみました。
aws-2.3.9/lib/awsbase/right_awsbase.rb

        def self.sign_request_v2(aws_secret_access_key, service_hash, http_verb, host, uri)
            fix_service_params(service_hash, '2')
            # select a signing method (make an old openssl working with sha1)
            # make 'HmacSHA256' to be a default one
            service_hash['SignatureMethod'] = 'HmacSHA256' unless ['HmacSHA256', 'HmacSHA1'].include?(service_hash['SignatureMethod'])
            service_hash['SignatureMethod'] = 'HmacSHA1' unless @@digest256

            #FORCE ConsistentRead
            service_hash['ConsistentRead'] = 'true'

            # select a digest
            digest = (service_hash['SignatureMethod'] == 'HmacSHA256' ? @@digest256 : @@digest1)
            # form string to sign
            canonical_string = service_hash.keys.sort.map do |key|
                "#{amz_escape(key)}=#{amz_escape(service_hash[key])}"
            end.join('&')

            string_to_sign = "#{http_verb.to_s.upcase}\n#{host.downcase}\n#{uri}\n#{canonical_string}"
            # sign the string
            signature = escape_sig(Base64.encode64(OpenSSL::HMAC.digest(digest, aws_secret_access_key, string_to_sign)).strip)
            ret = "#{canonical_string}&Signature=#{signature}"
#            puts 'full=' + ret.inspect
            ret
        end


この

service_hash['ConsistentRead'] = 'true'

一行を追加です。


これでConsistentReadできているようです(たぶん)
クエリーごとに指定できるようなのがほんとはええわな。

Eventually Consistentなデータストアを使う開発では気をつけよう。