6
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

CloudPubSubでhashデータをpublishするときにハマった

Posted at

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化して送りましょう。

6
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?