CloudPubSubでhashデータをpublishするときにハマった
Cloud Pubsubにhashでメッセージを送ったときに、全部文字列になってハマったよって話
結論
hashデータはto_jsonするなどしてstring化してpublishしよう
何が起きたか
RubyでPubsubにpublishする際、色んなパラメータを渡したいのでHashに色々突っ込んで送っていた
Google::Cloud::Pubsub(params).topic(:hoge_topic).publish data
これでpubsubが普通にkickできるのだが、Cloud Functionsのattributesで受け取った際にevent['attributes']['hoge'] == Trueのような比較で想定通りに通らなくなった。
よくよくデータを見てみたところ、Ruby側でHashを送るとkey:valueのペアごとにstring化されてしまっている。
publish側
require 'google/cloud/pubsub'
pubsub = Google::Cloud::Pubsub.new({ project_id: 'consulting-cloud-dev', credentials: 'credential.json'})
pubsub.topic(:hoge_topic).publish({ 'true': true, 'false': false, 'nil': nil, 'num': 1, 'float': 3.4 })
subscribe側 (python on Cloud Functions)
def hello_pubsub(event, context):
print(event['attributes'])
Stackdriver上のログ
{'false': 'false', 'float': '3.4', 'nil': '', 'num': '1', 'true': 'true'}
全部''で囲われていて文字列扱いになっている。うーん。
ライブラリの実装を見る
ライブラリ側の実装を見ると、Hashの場合はそれぞれstring化されてる。
https://github.com/googleapis/google-cloud-ruby/blob/master/google-cloud-pubsub/lib/google/cloud/pubsub/batch_publisher.rb#L91
コメントにはprotobuf definitionと書いてあるのでprotobufを想定しているということなのか。
なるほどー。確かにJSONとは限らないですね。
def create_pubsub_message data, attributes
attributes ||= {}
if data.is_a?(::Hash) && attributes.empty?
attributes = data
data = nil
end
# Convert IO-ish objects to strings
if data.respond_to?(:read) && data.respond_to?(:rewind)
data.rewind
data = data.read
end
# Convert data to encoded byte array to match the protobuf defn
data_bytes = \
String(data).dup.force_encoding(Encoding::ASCII_8BIT).freeze
# Convert attributes to strings to match the protobuf definition
attributes = Hash[attributes.map { |k, v| [String(k), String(v)] }]
Google::Pubsub::V1::PubsubMessage.new data: data_bytes,
attributes: attributes
end
地味に何故メッセージ送ってるのに、Cloud Functions側でmessageに入らずattributesに入ってくるのかもここで把握。
この関数で切り替わってたのか。
json化すればok
to_jsonつけた
require 'google/cloud/pubsub'
pubsub = Google::Cloud::Pubsub.new({ project_id: 'consulting-cloud-dev', credentials: 'credential.json'})
pubsub.topic(:hoge_topic).publish({ 'true': true, 'false': false, 'nil': nil, 'num': 1, 'float': 3.4 }.to_json)
subscribe側のログ
{"true":true,"false":false,"nil":null,"num":1,"float":3.4}
nilはnullになってるし、値も元の型になってる。
messageはstring化して送りましょう。
Author And Source
この問題について(CloudPubSubでhashデータをpublishするときにハマった), 我々は、より多くの情報をここで見つけました https://qiita.com/kshibata101/items/e0584c60298b148c66cc著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .