====== 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|