stompserver を動かしてみました

ひさしぶりに見てみたら、去年一週間くらいで開発されて以来の更新があったようです。パッケージ構成も一新されているので、だいぶリファクタリングされたように思えます。

  • 0.9.7 の lib以下
|-frame_journal.rb
|-queue_manager.rb
|-stomp_frame.rb
|-stomp_server.rb
|-topic_manager.rb
  • 0.9.8 の lib 以下
|-stomp_server.rb
|-stompserver
  |-prptocols
    |-http.rb
    |-stomp.rb
  |-queue
    |-activerecord_queue.rb
    |-ar_message.rb
    |-dbm_queue.rb
    |-file_queue.rb
    |-memory_queue.rb
  |-queue_manager.rb
  |-stomp_auth.rb
  |-stomp_frame.rb
  |-stomp_id.rb
  |-stomp_user.rb
  |-test_server.rb
  |-topic_manager.rb

というわけで、stompserver をインストール。

% sudo gem install stompserver -y
Password:
Need to update 3 gems from http://gems.rubyforge.org
...
complete
Successfully installed stompserver-0.9.8
Installing ri documentation for stompserver-0.9.8...
Installing RDoc documentation for stompserver-0.9.8...       


とりあえず、README を読んでみます。
#Rubyforge のサイトから辿れる RDoc の README は、なぜか途中で文中に "--" を入れてしまって RDoc の生成対象外になってしまっているので、ローカル環境のほうを見ましょう。

適当な作業ディレクトリを用意して起動します。

% cd /Users/kiwamu/work/stomp
% stompserver -p 61613 -b 0.0.0.0 -q file -s .stompfile
/usr/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `gem_original_require': no such file to load -- eventmachine (LoadError)
        from /usr/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `require'
        from /usr/local/lib/ruby/gems/1.8/gems/stompserver-0.9.8/lib/stomp_server.rb:2
        from /usr/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:32:in `gem_original_require'
        from /usr/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:32:in `require'
        from /usr/local/lib/ruby/gems/1.8/gems/stompserver-0.9.8/bin/stompserver:5
        from /usr/local/bin/stompserver:16:in `load'
        from /usr/local/bin/stompserver:16
%


ふむ。eventmachine もいるみたい?
ではインストールしましょう。gem の依存関係では指定されてなかったのか...?

% sudo gem install eventmachine -y
Password:
                     
Select which gem to install for your platform (i686-darwin8.8.1)                    
 1. eventmachine 0.9.0 (ruby)    
 2. eventmachine 0.8.1 (ruby)    
 3. eventmachine 0.8.1 (x86-mswin32)
 4. eventmachine 0.8.0 (ruby)    
 5. Skip this gem                
 6. Cancel installation          
>1                              
Building native extensions.  This could take a while...
Successfully installed eventmachine-0.9.0
Installing ri documentation for eventmachine-0.9.0...
Installing RDoc documentation for eventmachine-0.9.0...


気をとりなおして、もっかい起動してみます。

% stompserver -p 61613 -b 0.0.0.0 -q file -s .stompfile
Queue initialized in /usr/local/lib/ruby/gems/1.8/gems/stompserver-0.9.8/bin/.stompfile
TopicManager initialized
QueueManager initialized
Stomp protocol handler starting on 0.0.0.0 port 61613


今度はうまくいきました。
クライアントからつないでみます。stomp を gem インストールしといた上で、こんな感じにメッセージを send します。

% irb
>> require 'rubygems'
=> []                            
>> require 'stomp'               
=> ["Stomp"]                     
>> client = Stomp::Client.open "login", "passcode", "localhost", 61613
=> #<Stomp::Client:0x14b5fcc @running=true, @id_mutex=#<Mutex:0x14b5fa4>, @listeners={}, @receipt_listeners={}, @listener_thread=#<Thread:0x14b5db0 sleep>, @connection=#<Stomp::Connection:0x14b5f7c @socket=#<TCPSocket:0x14b5ef0>, @passcode="passcode", @host="localhost", @failure=nil, @port=61613, @socket_semaphore=#<Mutex:0x14b5f2c>, @login="login", @subscriptions={}, @read_semaphore=#<Mutex:0x14b5f40>, @connect=#<Stomp::Message:0x14b5d74 @command="CONNECTED", @body="", @headers={"session"=>"wow"}>, @reconnectDelay=5, @transmit_semaphore=#<Mutex:0x14b5f54>, @closed=false, @reliable=false>, @replay_messages_by_txn={}, @ids=1>
>> m = "Hello, world!"           
=> "Hello, world!"               
>> client.send("/queue/test", m, {
?>       "Persistent" => true,   
?>       "Client-id" => "Client1",
?>       "Reply-to" => "/queue/test",
?>       }                       
>>   )                           
=> nil                           
>> client.close                  
=> false


サーバ側のコンソールにはこんな表示が出力されます。

Sending a message to /queue/test: MESSAGE
Client-id:Client1                
Persistent:true                  
content-type:text/plain; charset=UTF-8
destination:/queue/test          
content-length:13                
Reply-to:/queue/test             
                                 
Hello, world!                    
Disconnecting             


ファイルに永続化されているであろうメッセージを見てみましょう。

% pwd
/Users/kiwamu/work/stomp/.stompfile
% less qinfo
"qinfo" may be a binary file.  See it anyway? 
^{^G:^Kqueues{^F"^P/queue/test{^L:^Nqueue_dir"S/User/kiwamu/work/stomp/.stompfile/_queue_test:
msgidi^G:^Menqueuedi^F:^Oexceptionsi^@:^Kframes[^F"$kiwamu-imac-1194944442-373753-1:
        sizei^F:^Mdequeuedi^@;
{^F"^P/queue/test{^F"$kiwamu-imac-1194944442-373753-1{^F;       i^@

% cd _queue_test 
% pwd
/Users/kiwamu/work/stomp/.stompfile/_queue_test
% ls -l
total 8
-rw-r--r--   1 kiwamu  wheel  291 Nov 13 18:30 kiwamu-imac-1194946234-907088-1
% less kiwamu-imac-1194946234-907088-1 
"kiwamu-imac-1194946234-907088-1" may be a binary file.  See it anyway? 
000001060000000d^o:^\StompServer::StompFram:
@body"^@:^M@command"^LMESSAGE:^M@headers{^L"^NClient-id"^LClient1"^Omessage-id"$kiwa
mu-imac-1194946234-907088-1"^OPersistent"       true"^Qcontent-type"^^text/plain; ch
arset=UTF-8"^Pdestination"^P/queue/test"^Scontent-length"^G13"^MReply-to"^P/queue/te
stHello, world!


メッセージを subscribe してみます。

>> client.subscribe("/queue/test", {
?>                       "Persistent" => true,
?>                       "Client-id" => "rubyClient",
?>               } ) do |message|
?>     puts message.inspect
>>   end
=> nil
>> #<Stomp::Message:0x770b8c @command="MESSAGE", @body="Hello, world!", @headers={"Client-id"=>"Client1", "message-id"=>"kiwamu-imac-1194946234-907088-1", "Persistent"=>"true", "content-type"=>"text/plain; charset=UTF-8", "destination"=>"/queue/test", "content-length"=>"13", "Reply-to"=>"/queue/test"}>


さきほど send したメッセージが表示され、キューのなかのファイルもなくなりました。

% pwd
/Users/kiwamu/work/stomp/.stompfile/_queue_test
% ls -l
ls: .: No such file or directory


subscribe 状態は client からの接続を close するまで続くので、以後、メッセージを send するとすぐにそれを取得します。
ちなみに subscribe のブロックのなかでこけるとメッセージも一緒に消えてしまいました... トランザクショナルに扱いたいときにはどうするんだろ?


冒頭でみた stompserver/protocols 以下の http.rb がとても気になりますが、デフォルトでは利用されていません。でも、bin/stompserver をいじると HTTP ハンドラを開始できるようです。これを使うと、RESTful に サーバにアクセスできそうな予感。ここから先はあとで... (^^;



参考リンク