読者です 読者をやめる 読者になる 読者になる

Masteries

技術的なことや仕事に関することを書いていきます.

SocketIO::EmitterがCPANで公開されました!

以前, PerlからSocket.IOのイベントをEmitするという記事で, PerlからSocket.IOのイベントをemit(発火)するSocketIO::Emitterというモジュールがあるという話をしました.

github.com

こちら, 作者の@toritori0318さんに「CPANで公開できませんでしょうか?」とお願いしたところ, 快諾頂きまして, 今後はcpanmやCartonで普通に使えるようになります.

metacpan.org

本当にありがとうございます!

注意点

以下, SocketIO::Emitterを使うにあたって幾つか注意すべき点があるので, 記しておきます.

SocketIO::Emitterとsocket.io-emitter/socket.io-redisのバージョンについて

SocketIO::Emitterは, socket.io-emitterのPerl実装ですが, socket.io-emitterは途中で大きく実装が変わっています. そしてSocketIO::Emitter/socket.io-emitterを使うにあたっては, Node側でsocket.io-redisを利用する必要があるのですが, これのバージョンについても考慮しなければなりません.

具体的には,

  • socket.io-emitter 0.2.0以前 + socket.io-redis 0.1.4以前 ... SocketIO::Emitter 0.01
  • socket.io-emitter 0.3.0以降 + socket.io-redis 0.2.0以降 ... SocketIO::Emitter 0.03以降

という対応になっています.

socket.io-emitter 0.3.0/socket.io-redis 0.2.0は2015年12月上旬にリリースされているので, それ以降に開発がスタートしたプロダクトであればSocketIO::Emitterの最新版を使っておけば概ね問題はないでしょう. それ以前からSocket.IOを使って開発しているプロダクトの場合, socket.io-emitter/socket.io-redisの1.0.0が2015年12月中旬にリリースされているので, タイミングを見計らってこちらに切り替えることをおすすめします.

SocketIO::Emitter 0.02について

tl;dr: SocketIO::Emitter 0.02は, socket.io-emitter 0.3.0以降/socket.io-redis 0.2.0以降に対応したバージョンですが, 内部で利用しているData::MessagePackのバージョンの都合でうまく動きませんので使わないでください

SocketIO::Emitter 0.01は, socket.io-emitter 0.2.0以前/socket.io-redis 0.1.4以前に対応した実装になっていて, その後Pull Requestを出させて頂いて, socket.io-emitter 0.3.0以降/socket.io-redis 0.2.0以降に対応したSocketIO::Emitter 0.02になりました.

...ところで, SocketIO::Emitterはその内部でData::MessagePackを使っています. これは, SocketIO::Emitterやsocket.io-emitterがイベントをemitするにあたって, 次のような仕組みで動作しているからです.

  • emitするイベントの情報をMessagePackでシリアライズして, Redisに投げ込む
  • 投げ込まれたデータを, Redisが配信する
  • socket.io-redisがRedisから配信されたデータを受け取って, デシリアライズする
  • この情報を使って, イベントの処理を行う

Data::MessagePackについては, つい先日新しいフォーマットに対応した0.50がリリースされていて, SocketIO::Emitterのリリースに向けて@toritori0318さんと相談している際, Data::MessagePackの0.50を利用するようにしましょう, というお話をしていて, 実際そのようになりました.

...が, 何故か手元の環境では, SocketIO::Emitterによるイベントのemitは成功するのですが, それをsocket.io-redisが処理する際, デシリアライズで失敗するという状況に. いろいろ調べていたところ, 次のような事情がわかってきました:

  • MessagePackについては, 古い仕様新しい仕様がある
  • Data::MessagePackの0.49以前は古い仕様, 0.50は新しい仕様に従って実装されている(っぽい)
  • socket.io-redisは, MessagePackのシリアライズ/デシリアライズにmsgpack-jsを使っている
    • npmにおいて, msgpack-jsは, MessagePackの古い仕様に従って実装されたものとして公開されている
    • npmにおいて, MessagePackの新しい仕様に従った実装はmsgpack-js-v5として公開されている

実際, 無理やりsocket.io-redisでmsgpack-jsではなくmsgpack-js-v5を使うようにしてみると, SocketIO::Emitter 0.02(Data::MessagePack 0.50を利用)でも問題なく動くことを確認できたので, MessagePackのシリアライザ/でシリアライザのバージョンというか, 仕様の違いが原因... のようでした.

今回は, @toritori0318さんに, SocketIO::Emitterが要求するData::MessagePackのバージョンを0.49以上に設定して頂いて, モジュールを使う側はcpanfileを,

requires 'Data::MessagePack', '== 0.49';
requires 'SocketIO::Emitter', '>= 0.03';

とする, という形で対応しました.

とはいえ, この場合, Data::MessagePack 0.50以降を使いたい, という場合対応できなくなってしまうので(自分たちの環境の場合, Data::MessagePackはSocketIO::Emitterのためにしか使わないので, これでも問題ないのですが...), socket.io-redisがmsgpack-js-v5を使うようになるか, 或いはData::MessagePackが"古い仕様"と"新しい仕様"の両方に対応するか... 辺りが必要なのかなあ, と思います.

まとめ

最近取り組んでいた, SocketIO::Emitterについてのまとめです. ちょっとこう, 雑多な感じがしたので, Qiitaではなくブログにまとめてみることになりました.

最後になりましたが, @toritori0318さんには, CPANへのリリース作業だけでなく, 0.02における原因調査など, いろいろお手伝いくださって本当に感謝しています. この場を借りて御礼申し上げます. ありがとうございました!