処理する必要がある一連の JSON メッセージがあり、文字エンコーディングで問題が発生しました。次のように、RabbitMQ キューからこのメッセージを取得します。
@data = []
@queue.pop do |metadata, payload|
parsed_message = JSON.parse(payload)
@data << parsed_message
end
次に、Resque を使用してそれらを処理し、次のようにキューに入れます。
Resque.enqueue(Worker, @data)
ワーカーを実行すると、次のエラーがスローされます。
** [16:06:13 2012-09-14] 5375: Error reserving job: #<Encoding::InvalidByteSequenceError: "\xC3" on US-ASCII>
** [16:06:13 2012-09-14] 5375: /usr/local/lib/ruby/1.9.1/json/common.rb:148:in `encode'
/usr/local/lib/ruby/1.9.1/json/common.rb:148:in `initialize'
/usr/local/lib/ruby/1.9.1/json/common.rb:148:in `new'
/usr/local/lib/ruby/1.9.1/json/common.rb:148:in `parse'
/usr/local/lib/ruby/gems/1.9.1/gems/multi_json-1.3.6/lib/multi_json/adapters/json_common.rb:7:in `load'
/usr/local/lib/ruby/gems/1.9.1/gems/multi_json-1.3.6/lib/multi_json.rb:93:in `load'
/usr/local/lib/ruby/gems/1.9.1/gems/resque-1.22.0/lib/resque/helpers.rb:38:in `decode'
/usr/local/lib/ruby/gems/1.9.1/gems/resque-1.22.0/lib/resque.rb:149:in `pop'
/usr/local/lib/ruby/gems/1.9.1/gems/resque-1.22.0/lib/resque/job.rb:100:in `reserve'
/usr/local/lib/ruby/gems/1.9.1/gems/resque-1.22.0/lib/resque.rb:303:in `reserve'
/usr/local/lib/ruby/gems/1.9.1/gems/resque-1.22.0/lib/resque/worker.rb:209:in `block in reserve'
/usr/local/lib/ruby/gems/1.9.1/gems/resque-1.22.0/lib/resque/worker.rb:207:in `each'
/usr/local/lib/ruby/gems/1.9.1/gems/resque-1.22.0/lib/resque/worker.rb:207:in `reserve'
/usr/local/lib/ruby/gems/1.9.1/gems/resque-1.22.0/lib/resque/worker.rb:136:in `block in work'
/usr/local/lib/ruby/gems/1.9.1/gems/resque-1.22.0/lib/resque/worker.rb:133:in `loop'
/usr/local/lib/ruby/gems/1.9.1/gems/resque-1.22.0/lib/resque/worker.rb:133:in `work'
/usr/local/lib/ruby/gems/1.9.1/gems/resque-1.22.0/lib/resque/tasks.rb:36:in `block (2 levels) in <top (required)>'
/usr/local/lib/ruby/1.9.1/rake/task.rb:205:in `call'
/usr/local/lib/ruby/1.9.1/rake/task.rb:205:in `block in execute'
/usr/local/lib/ruby/1.9.1/rake/task.rb:200:in `each'
/usr/local/lib/ruby/1.9.1/rake/task.rb:200:in `execute'
/usr/local/lib/ruby/1.9.1/rake/task.rb:158:in `block in invoke_with_call_chain'
/usr/local/lib/ruby/1.9.1/monitor.rb:211:in `mon_synchronize'
/usr/local/lib/ruby/1.9.1/rake/task.rb:151:in `invoke_with_call_chain'
/usr/local/lib/ruby/1.9.1/rake/task.rb:144:in `invoke'
/usr/local/lib/ruby/1.9.1/rake/application.rb:116:in `invoke_task'
/usr/local/lib/ruby/1.9.1/rake/application.rb:94:in `block (2 levels) in top_level'
/usr/local/lib/ruby/1.9.1/rake/application.rb:94:in `each'
/usr/local/lib/ruby/1.9.1/rake/application.rb:94:in `block in top_level'
/usr/local/lib/ruby/1.9.1/rake/application.rb:133:in `standard_exception_handling'
/usr/local/lib/ruby/1.9.1/rake/application.rb:88:in `top_level'
/usr/local/lib/ruby/1.9.1/rake/application.rb:66:in `block in run'
/usr/local/lib/ruby/1.9.1/rake/application.rb:133:in `standard_exception_handling'
/usr/local/lib/ruby/1.9.1/rake/application.rb:63:in `run'
/usr/local/bin/rake:32:in `<main>'
rake aborted!
ワーカーからの実行関数のすべてのコードを begin/rescue ブロックでラップして、例外をキャッチしようとしましたが、役に立たなかったため、Resque のどこかにあると思いました。
Resque ワーカーに生データをエンキューしてから、ワーカー内で JSON に解析し、UTF-8 エンコーディングを設定しようとしました。
raw_data.each do |msg|
msg = msg.encode("UTF-8", :invalid => :replace, :undef => :replace, :replace => "")
parsed_msg = JSON.parse(msg) rescue nil
next if parsed_msg.nil?
parsed_data << parsed_msg
end
それでも同じエラーが発生します。常に同じ文字であるとは限りません。記憶が正しければ、\xC2 または \xD8 の場合もあります。
何か案は?