====== AlWorker JavaScriptからIPCをコールする ====== ===== 背景 ===== ブラウザでボタンが押された等のアクションを最終的にワーカーのIPCサービスが処理する場合、 伝達経路が長く、使われるテクノロジーも多いので、ユーザープログラムが煩雑でデバッグもとても大変になります。 {{:alworker:ipcimage1.png?nolink|}} そこで、2つのライブラリを使ってこの複雑さを隠蔽し、JavaScriptからWorkerのネイティブコードを呼び出すことができるようにしました。 (利用イメージ)\\ {{:alworker:ipcimage2.png?nolink|}} ====== 使い方 ====== ===== 1. JavaScript "alone.js" ライブラリを読み込む ===== htmlで、alone.jsが読み込まれる様に記述する。 ===== 2. AlControllerへIpcActionモジュールをincludeする ===== cgiコントローラ内に次のように記述する。 require "al_form" require "al_worker_ipc" class AlController include AlWorker::IpcAction ===== 3. JavaScriptからコールする ===== var ipc = new Alone.Ipc(); ipc.call( "NAME", { any_parameters: "any value" } ); ===== 注意 ===== AlWorker::IpcActionをincludeすることで、すべてのIPCをHTTP経由で外部に公開することになります。\\ セキュリティー上の理由などにより公開してはならないIPCがある場合、IPCソケットを公開用、非公開用に分離するか、module AlWorker::IpcActionを参考に、独自にメソッドを追加してください。 ====== サンプル ====== 画面上のカウンタ(数字)を、ボタン操作によってアップダウンさせる。 ===== 常駐サーバー ===== あらかじめ、ウェブサーバーと同じマシンで実行しておく。 require "al_worker_ipc" class CountServer < AlWorker def initialize2() @ipc = Ipc.new() @ipc.chmod = 0666 @ipc.run( self ) set_value( "counter", 0 ) end # IPCコマンド counter を定義 # (note) # 引数 param には、JavaScript側の callで指定したパラメータがそのまま渡ってくる。 def ipc_counter( sock, param ) counter = get_value( "counter" ) case param["work"] when "up" counter += 1 when "down" counter -= 1 end set_value( "counter", counter ) # 第4引数は、JavaScript側へそのまま返される。 reply( sock, 200, "OK", {"counter"=>counter} ) end end server = CountServer.new( "count_server" ) server.parse_option() server.daemon() ===== Alone cgiコントローラ ===== require "al_template" require "al_form" require "al_worker_ipc" class AlController include AlWorker::IpcAction def initialize() @ipc = AlWorker::Ipc.open( "/tmp/count_server" ) end def action_index() @ipc.get_values() AlTemplate.run( "index.rhtml" ) end end ===== 画面テンプレートとJavaScript ===== <%= header_section %> <%= body_section %> カウンター <%=h @ipc.values["counter"] %>
<%= footer_section %>
====== 個別機能 ====== ===== JavaScript ライブラリ ===== IPCの戻り値 success コールバックファンクションの第一パラメータで取得する方法と、ipc オブジェクトの、dataアトリビュートで取得する方法の2種類があります。\\ 一般的にはコールバックファンクションを使う方が、やりやすいでしょう。 AJAX jQueryが読み込まれていれば、AJAX接続にjQuery.ajax メソッドを使うようになります。\\ その場合、ipc.options が jQuery.ajax メソッド用の接続オプションとして使われますので、接続条件などを変更できます。\\ ===== IPC接続先指定 ===== IPCの接続先指定の方法は、4種類あります。 1. コントローラのコンストラクタ等で @ipc オブジェクトを生成する。(推奨) def initialize() @ipc = AlWorker::Ipc.open( "/tmp/chat_server" ) 2. コントローラのコンストラクタ等で、@ipc_name でソケット名を与える。 def initialize() @ipc_name = "/tmp/chat_server" 3. httpリクエストに含める JavaScriptから ipc.call( "say", { message: "anything", ipc_name: "/tmp/chat_server" } ); 4. デフォルト値を使用 何も指示しなければ、/tmp/al_worker をデフォルト値として使用し、IPC接続しようとする。 ====== プロトコル詳細 ====== ===== cgiリクエスト ===== リクエストパラメータは、以下のようになります。 http://*.cgi?ctrl=xxx&action=ipc&ipc=IPCNAME&arg=ARGUMENT_encoded_by_json ^パラメータ^意味^備考^ |ctrl|Aloneコントローラ| |action|Aloneアクション|ipc固定| |ipc|IPC名の指示| |arg|引数 JSONエンコード| ===== 戻り値 ===== 以下の、2要素の配列が返ります。 [IPCステータスコード, 戻り値をJSONエンコード] ^index^内容^データタイプ^保存先^ |0|IPCステータスコード|String|ipc.status_code| |1|戻り値|Hash(Object)|ipc.data|