sinatra-rocketio-linda 0.2.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/History.txt +4 -0
- data/README.md +3 -3
- data/Rakefile +1 -0
- data/lib/js/linda.js +9 -3
- data/lib/sinatra-rocketio-linda/linda.rb +4 -2
- data/lib/sinatra-rocketio-linda/tuple.rb +7 -0
- data/lib/sinatra/rocketio/linda/client.rb +27 -6
- data/lib/sinatra/rocketio/linda/version.rb +1 -1
- data/linda.js +10 -4
- data/linda.min.js +2 -2
- data/sample/bin/cui_calc_watcher.rb +2 -2
- data/sample/bin/cui_calc_worker.rb +2 -2
- data/sample/public/client.js +2 -1
- data/sample/public/worker.js +1 -1
- data/sinatra-rocketio-linda.gemspec +1 -1
- data/test/test_client_disconnect.rb +4 -4
- data/test/test_rubyclient.rb +46 -11
- metadata +7 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 80ea427ebe1d5b5567614294e23521c21878ea81
|
4
|
+
data.tar.gz: 9939c563e0d718a87ad755187efd8c8eb3452b4c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 62affc882c4199c103f37c6788d277748d6517140dd1d9e8c696530899981e10f8f5a40c9b2e540a00defc90cc1f001a1858480ca370851a036fda89000c1f23
|
7
|
+
data.tar.gz: 31bfd9e8adb98c70eac4578d130455eda41bfd3486a3e80c6e9f34386492dd959cac334ac95063ecb238437ca3aace28bf0cc4017d03100a5f04a321d80ba683
|
data/History.txt
CHANGED
data/README.md
CHANGED
@@ -89,7 +89,7 @@ $("#btn_request").click(function(){
|
|
89
89
|
|
90
90
|
// wait result
|
91
91
|
var take_result = function(){
|
92
|
-
ts.take(["calc_result"], function(tuple){
|
92
|
+
ts.take(["calc_result"], function(tuple, info){
|
93
93
|
var result = tuple[1]; // from 'worker' side
|
94
94
|
console.log(result);
|
95
95
|
take_result(); // recursive call
|
@@ -106,7 +106,7 @@ var ts = new linda.TupleSpace("calc");
|
|
106
106
|
|
107
107
|
// calculate
|
108
108
|
var calc = function(){
|
109
|
-
ts.take(["calc_request"], function(tuple){
|
109
|
+
ts.take(["calc_request"], function(tuple, info){
|
110
110
|
var query = tuple[1]; // => "1-2+3*4"
|
111
111
|
var result = eval(query);
|
112
112
|
console.log(query+" = "+result); // => "1-2+3*4 = 11"
|
@@ -129,7 +129,7 @@ ts = linda.tuplespace["calc"]
|
|
129
129
|
|
130
130
|
## calculate
|
131
131
|
calc = lambda{
|
132
|
-
ts.take ["calc_request"] do |tuple|
|
132
|
+
ts.take ["calc_request"] do |tuple, info|
|
133
133
|
query = tuple[1] ## => "1-2+3*4"
|
134
134
|
result = eval(query)
|
135
135
|
puts "calc: #{query} = #{result}" ## => "1-2+3*4 = 11"
|
data/Rakefile
CHANGED
data/lib/js/linda.js
CHANGED
@@ -25,21 +25,27 @@ var Linda = function(io, opts){
|
|
25
25
|
if(tuple === null || typeof tuple !== "object") return;
|
26
26
|
if(typeof callback !== "function") return;
|
27
27
|
var callback_id = make_callback_id();
|
28
|
-
self.io.once("__linda_read_callback_"+callback_id,
|
28
|
+
self.io.once("__linda_read_callback_"+callback_id, function(data){
|
29
|
+
callback(data.tuple, data.info);
|
30
|
+
});
|
29
31
|
self.io.push("__linda_read", [space.name, tuple, callback_id]);
|
30
32
|
};
|
31
33
|
this.take = function(tuple, callback){
|
32
34
|
if(tuple === null || typeof tuple !== "object") return;
|
33
35
|
if(typeof callback !== "function") return;
|
34
36
|
var callback_id = make_callback_id();
|
35
|
-
self.io.once("__linda_take_callback_"+callback_id,
|
37
|
+
self.io.once("__linda_take_callback_"+callback_id, function(data){
|
38
|
+
callback(data.tuple, data.info);
|
39
|
+
});
|
36
40
|
self.io.push("__linda_take", [space.name, tuple, callback_id]);
|
37
41
|
};
|
38
42
|
this.watch = function(tuple, callback){
|
39
43
|
if(tuple === null || typeof tuple !== "object") return;
|
40
44
|
if(typeof callback !== "function") return;
|
41
45
|
var callback_id = make_callback_id();
|
42
|
-
self.io.on("__linda_watch_callback_"+callback_id,
|
46
|
+
self.io.on("__linda_watch_callback_"+callback_id, function(data){
|
47
|
+
callback(data.tuple, data.info);
|
48
|
+
});
|
43
49
|
self.io.push("__linda_watch", [space.name, tuple, callback_id]);
|
44
50
|
};
|
45
51
|
};
|
@@ -48,7 +48,9 @@ Sinatra::RocketIO.on :__linda_write do |data, client|
|
|
48
48
|
end
|
49
49
|
opts = opts_
|
50
50
|
end
|
51
|
-
|
51
|
+
opts[:from] = client.address
|
52
|
+
_tuple = Sinatra::RocketIO::Linda::Tuple.new tuple, opts
|
53
|
+
Sinatra::RocketIO::Linda[space].write _tuple
|
52
54
|
Sinatra::RocketIO::Linda.emit :write, Hashie::Mash.new(:space => space, :tuple => tuple), client
|
53
55
|
end
|
54
56
|
|
@@ -65,7 +67,7 @@ end
|
|
65
67
|
next
|
66
68
|
end
|
67
69
|
callback_id = Sinatra::RocketIO::Linda[space].__send__ func, tuple do |tuple|
|
68
|
-
Sinatra::RocketIO.push "__linda_#{func}_callback_#{callback}", tuple, :to => client.session
|
70
|
+
Sinatra::RocketIO.push "__linda_#{func}_callback_#{callback}", {:tuple => tuple.data, :info => {:from => tuple.from}}, :to => client.session
|
69
71
|
Sinatra::RocketIO::Linda.emit func, Hashie::Mash.new(:space => space, :tuple => tuple), client
|
70
72
|
end
|
71
73
|
Sinatra::RocketIO::Linda.callbacks[client.session].push(:space => space, :callback => callback_id)
|
@@ -5,6 +5,13 @@ module Sinatra
|
|
5
5
|
module Linda
|
6
6
|
# use linda gem (https://rubygems.org/gems/linda)
|
7
7
|
class Tuple < ::Linda::Tuple
|
8
|
+
|
9
|
+
attr_reader :from
|
10
|
+
def initialize(data, opts={})
|
11
|
+
@from = opts[:from] if opts.kind_of? Hash
|
12
|
+
super data, opts
|
13
|
+
end
|
14
|
+
|
8
15
|
end
|
9
16
|
end
|
10
17
|
end
|
@@ -1,11 +1,15 @@
|
|
1
1
|
require File.expand_path 'version', File.dirname(__FILE__)
|
2
2
|
require 'event_emitter'
|
3
|
+
require 'hashie'
|
3
4
|
require 'sinatra/rocketio/client'
|
4
5
|
|
5
6
|
module Sinatra
|
6
7
|
module RocketIO
|
7
8
|
module Linda
|
8
9
|
|
10
|
+
class TupleInfo < Hashie::Mash
|
11
|
+
end
|
12
|
+
|
9
13
|
class Client
|
10
14
|
attr_reader :io, :tuplespace
|
11
15
|
def initialize(io_or_url)
|
@@ -46,8 +50,12 @@ module Sinatra
|
|
46
50
|
unless [Hash, Array].include? tuple.class
|
47
51
|
raise ArgumentError, "tuple must be Array or Hash"
|
48
52
|
end
|
49
|
-
callback_id =
|
50
|
-
|
53
|
+
callback_id = create_callback_id
|
54
|
+
if block_given?
|
55
|
+
@linda.io.once "__linda_read_callback_#{callback_id}" do |data|
|
56
|
+
block.call(data['tuple'], TupleInfo.new(data['info']))
|
57
|
+
end
|
58
|
+
end
|
51
59
|
@linda.io.push "__linda_read", [@name, tuple, callback_id]
|
52
60
|
end
|
53
61
|
|
@@ -55,8 +63,12 @@ module Sinatra
|
|
55
63
|
unless [Hash, Array].include? tuple.class
|
56
64
|
raise ArgumentError, "tuple must be Array or Hash"
|
57
65
|
end
|
58
|
-
callback_id =
|
59
|
-
|
66
|
+
callback_id = create_callback_id
|
67
|
+
if block_given?
|
68
|
+
@linda.io.once "__linda_take_callback_#{callback_id}" do |data|
|
69
|
+
block.call(data['tuple'], TupleInfo.new(data['info']))
|
70
|
+
end
|
71
|
+
end
|
60
72
|
@linda.io.push "__linda_take", [@name, tuple, callback_id]
|
61
73
|
end
|
62
74
|
|
@@ -64,11 +76,20 @@ module Sinatra
|
|
64
76
|
unless [Hash, Array].include? tuple.class
|
65
77
|
raise ArgumentError, "tuple must be Array or Hash"
|
66
78
|
end
|
67
|
-
callback_id =
|
68
|
-
|
79
|
+
callback_id = create_callback_id
|
80
|
+
if block_given?
|
81
|
+
@linda.io.on "__linda_watch_callback_#{callback_id}" do |data|
|
82
|
+
block.call(data['tuple'], TupleInfo.new(data['info']))
|
83
|
+
end
|
84
|
+
end
|
69
85
|
@linda.io.push "__linda_watch", [@name, tuple, callback_id]
|
70
86
|
end
|
71
87
|
|
88
|
+
private
|
89
|
+
def create_callback_id
|
90
|
+
"#{Time.now.to_i}#{Time.now.usec}_#{(rand*1000000).to_i}"
|
91
|
+
end
|
92
|
+
|
72
93
|
end
|
73
94
|
|
74
95
|
end
|
data/linda.js
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
// Linda.js
|
1
|
+
// Linda.js v1.0.0 (rocketio v0.3.0)
|
2
2
|
// https://github.com/shokai/sinatra-rocketio-linda
|
3
3
|
// (c) 2013 Sho Hashimoto <hashimoto@shokai.org>
|
4
4
|
// The MIT License
|
@@ -29,21 +29,27 @@ var Linda = function(io, opts){
|
|
29
29
|
if(tuple === null || typeof tuple !== "object") return;
|
30
30
|
if(typeof callback !== "function") return;
|
31
31
|
var callback_id = make_callback_id();
|
32
|
-
self.io.once("__linda_read_callback_"+callback_id,
|
32
|
+
self.io.once("__linda_read_callback_"+callback_id, function(data){
|
33
|
+
callback(data.tuple, data.info);
|
34
|
+
});
|
33
35
|
self.io.push("__linda_read", [space.name, tuple, callback_id]);
|
34
36
|
};
|
35
37
|
this.take = function(tuple, callback){
|
36
38
|
if(tuple === null || typeof tuple !== "object") return;
|
37
39
|
if(typeof callback !== "function") return;
|
38
40
|
var callback_id = make_callback_id();
|
39
|
-
self.io.once("__linda_take_callback_"+callback_id,
|
41
|
+
self.io.once("__linda_take_callback_"+callback_id, function(data){
|
42
|
+
callback(data.tuple, data.info);
|
43
|
+
});
|
40
44
|
self.io.push("__linda_take", [space.name, tuple, callback_id]);
|
41
45
|
};
|
42
46
|
this.watch = function(tuple, callback){
|
43
47
|
if(tuple === null || typeof tuple !== "object") return;
|
44
48
|
if(typeof callback !== "function") return;
|
45
49
|
var callback_id = make_callback_id();
|
46
|
-
self.io.on("__linda_watch_callback_"+callback_id,
|
50
|
+
self.io.on("__linda_watch_callback_"+callback_id, function(data){
|
51
|
+
callback(data.tuple, data.info);
|
52
|
+
});
|
47
53
|
self.io.push("__linda_watch", [space.name, tuple, callback_id]);
|
48
54
|
};
|
49
55
|
};
|
data/linda.min.js
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
// Linda.js
|
1
|
+
// Linda.js v1.0.0 (rocketio v0.3.0)
|
2
2
|
// https://github.com/shokai/sinatra-rocketio-linda
|
3
3
|
// (c) 2013 Sho Hashimoto <hashimoto@shokai.org>
|
4
4
|
// The MIT License
|
5
|
-
var Linda=function(io,opts){var self=this;this.io=null;if(io===null||typeof io==="undefined"){this.io=(new RocketIO).connect()}else{this.io=io}this.opts=opts||{};this.TupleSpace=function(name){if(name===null||typeof name!=="string")name="__default__";this.name=name;this.linda=self;var space=this;var make_callback_id=function(){return new Date-0+"_"+Math.floor(Math.random()*1e6)};this.write=function(tuple,opts){if(tuple===null||typeof tuple!=="object")return;if(opts===null||typeof opts==="undefined")opts={};self.io.push("__linda_write",[space.name,tuple,opts])};this.read=function(tuple,callback){if(tuple===null||typeof tuple!=="object")return;if(typeof callback!=="function")return;var callback_id=make_callback_id();self.io.once("__linda_read_callback_"+callback_id,callback);self.io.push("__linda_read",[space.name,tuple,callback_id])};this.take=function(tuple,callback){if(tuple===null||typeof tuple!=="object")return;if(typeof callback!=="function")return;var callback_id=make_callback_id();self.io.once("__linda_take_callback_"+callback_id,callback);self.io.push("__linda_take",[space.name,tuple,callback_id])};this.watch=function(tuple,callback){if(tuple===null||typeof tuple!=="object")return;if(typeof callback!=="function")return;var callback_id=make_callback_id();self.io.on("__linda_watch_callback_"+callback_id,callback);self.io.push("__linda_watch",[space.name,tuple,callback_id])}}};var RocketIO=function(opts){(new EventEmitter).apply(this);if(typeof opts==="undefined"||opts===null)opts={};this.type=opts.type||null;this.session=opts.session||null;this.channel=null;if(typeof opts.channel!=="undefined"&&opts.channel!==null){this.channel=""+opts.channel}var setting={};this.io=null;var self=this;var ws_close_timer=null;self.on("__connect",function(session_id){self.session=session_id;self.io.push("__channel_id",self.channel);self.emit("connect")});this.connect=function(url){if(typeof url==="string"){$.getJSON(url+"/rocketio/settings",function(res){setting=res;connect_io()});return self}else{return connect_io()}};var connect_io=function(){self.io=function(){if(self.type==="comet")return;if(typeof WebSocketIO!=="function")return;var io=new WebSocketIO;if(typeof setting.websocket==="string")io.url=setting.websocket;io.session=self.session;return io.connect()}()||function(){if(typeof CometIO!=="function")return;var io=new CometIO;if(typeof setting.comet==="string")io.url=setting.comet;io.session=self.session;return io.connect()}();if(typeof self.io==="undefined"){setTimeout(function(){self.emit("error","WebSocketIO and CometIO are not available")},100);return self}if(self.io.url.match(/^ws:\/\/.+/))self.type="websocket";else if(self.io.url.match(/cometio/))self.type="comet";else self.type="unknown";self.io.on("*",function(event_name,args){if(event_name==="connect")event_name="__connect";self.emit(event_name,args)});ws_close_timer=setTimeout(function(){self.close();self.type="comet";connect_io()},3e3);self.once("connect",function(){if(ws_close_timer)clearTimeout(ws_close_timer);ws_close_timer=null});return self};this.close=function(){self.io.close()};this.push=function(type,data){self.io.push(type,data)}};var CometIO=function(url,opts){(new EventEmitter).apply(this);if(typeof opts==="undefined"||opts===null)opts={};this.url=url||"";this.session=opts.session||null;var running=false;var self=this;var post_queue=[];var flush=function(){if(!running||post_queue.length<1)return;var post_data={json:JSON.stringify({session:self.session,events:post_queue})};$.ajax({url:self.url,data:post_data,success:function(data){},error:function(req,stat,e){self.emit("error","CometIO push error")},complete:function(e){},type:"POST",dataType:"json",timeout:1e4});post_queue=[]};setInterval(flush,1e3);this.push=function(type,data){if(!running||!self.session){self.emit("error","CometIO not connected");return}post_queue.push({type:type,data:data})};this.connect=function(){if(running)return self;self.on("__session_id",function(session){self.session=session;self.emit("connect",self.session)});running=true;get();return self};this.close=function(){running=false;self.removeListener("__session_id")};var get=function(){if(!running)return;$.ajax({url:self.url+"?"+(new Date-0),data:{session:self.session},success:function(data_arr){if(data_arr!==null&&typeof data_arr=="object"&&!!data_arr.length){for(var i=0;i<data_arr.length;i++){var data=data_arr[i];if(data)self.emit(data.type,data.data)}}get()},error:function(req,stat,e){self.emit("error","CometIO get error");setTimeout(get,1e4)},complete:function(e){},type:"GET",dataType:"json",timeout:13e4})}};var WebSocketIO=function(url,opts){(new EventEmitter).apply(this);if(typeof opts==="undefined"||opts===null)opts={};this.url=url||"";this.session=opts.session||null;this.websocket=null;this.connecting=false;var reconnect_timer_id=null;var running=false;var self=this;self.on("__session_id",function(session_id){self.session=session_id;self.emit("connect",self.session)});this.connect=function(){if(typeof WebSocket==="undefined"){self.emit("error","websocket not exists in this browser");return null}self.running=true;var url=self.session?self.url+"/session="+self.session:self.url;self.websocket=new WebSocket(url);self.websocket.onmessage=function(e){var data_=null;try{data_=JSON.parse(e.data)}catch(e){self.emit("error","WebSocketIO data parse error")}if(!!data_)self.emit(data_.type,data_.data)};self.websocket.onclose=function(){if(self.connecting){self.connecting=false;self.emit("disconnect")}if(self.running){reconnect_timer_id=setTimeout(self.connect,1e4)}};self.websocket.onopen=function(){self.connecting=true};return self};this.close=function(){clearTimeout(reconnect_timer_id);self.running=false;self.websocket.close()};this.push=function(type,data){if(!self.connecting){self.emit("error","websocket not connected");return}self.websocket.send(JSON.stringify({type:type,data:data,session:self.session}))}};var EventEmitter=function(){var self=this;this.apply=function(target,prefix){if(!prefix)prefix="";for(var func in self){if(self.hasOwnProperty(func)&&func!=="apply"){target[prefix+func]=this[func]}}};this.__events=new Array;this.on=function(type,listener,opts){if(typeof listener!=="function")return;var event_id=self.__events.length>0?1+self.__events[self.__events.length-1].id:0;var params={id:event_id,type:type,listener:listener};for(i in opts){if(!params[i])params[i]=opts[i]}self.__events.push(params);return event_id};this.once=function(type,listener){self.on(type,listener,{once:true})};this.emit=function(type,data){for(var i=0;i<self.__events.length;i++){var e=self.__events[i];switch(e.type){case type:e.listener(data);if(e.once)e.type=null;break;case"*":e.listener(type,data);if(e.once)e.type=null;break}}self.removeListener()};this.removeListener=function(id_or_type){for(var i=self.__events.length-1;i>=0;i--){var e=self.__events[i];switch(typeof id_or_type){case"number":if(e.id===id_or_type)self.__events.splice(i,1);break;case"string":case"object":if(e.type===id_or_type)self.__events.splice(i,1);break}}}};if(typeof module!=="undefined"&&typeof module.exports!=="undefined"){module.exports=EventEmitter}
|
5
|
+
var Linda=function(io,opts){var self=this;this.io=null;if(io===null||typeof io==="undefined"){this.io=(new RocketIO).connect()}else{this.io=io}this.opts=opts||{};this.TupleSpace=function(name){if(name===null||typeof name!=="string")name="__default__";this.name=name;this.linda=self;var space=this;var make_callback_id=function(){return new Date-0+"_"+Math.floor(Math.random()*1e6)};this.write=function(tuple,opts){if(tuple===null||typeof tuple!=="object")return;if(opts===null||typeof opts==="undefined")opts={};self.io.push("__linda_write",[space.name,tuple,opts])};this.read=function(tuple,callback){if(tuple===null||typeof tuple!=="object")return;if(typeof callback!=="function")return;var callback_id=make_callback_id();self.io.once("__linda_read_callback_"+callback_id,function(data){callback(data.tuple,data.info)});self.io.push("__linda_read",[space.name,tuple,callback_id])};this.take=function(tuple,callback){if(tuple===null||typeof tuple!=="object")return;if(typeof callback!=="function")return;var callback_id=make_callback_id();self.io.once("__linda_take_callback_"+callback_id,function(data){callback(data.tuple,data.info)});self.io.push("__linda_take",[space.name,tuple,callback_id])};this.watch=function(tuple,callback){if(tuple===null||typeof tuple!=="object")return;if(typeof callback!=="function")return;var callback_id=make_callback_id();self.io.on("__linda_watch_callback_"+callback_id,function(data){callback(data.tuple,data.info)});self.io.push("__linda_watch",[space.name,tuple,callback_id])}}};var RocketIO=function(opts){(new EventEmitter).apply(this);if(typeof opts==="undefined"||opts===null)opts={};this.type=opts.type||null;this.session=opts.session||null;this.channel=null;if(typeof opts.channel!=="undefined"&&opts.channel!==null){this.channel=""+opts.channel}var setting={};this.io=null;var self=this;var ws_close_timer=null;self.on("__connect",function(session_id){self.session=session_id;self.io.push("__channel_id",self.channel);self.emit("connect")});this.connect=function(url){if(typeof url==="string"){$.getJSON(url+"/rocketio/settings",function(res){setting=res;connect_io()});return self}else{return connect_io()}};var connect_io=function(){self.io=function(){if(self.type==="comet")return;if(typeof WebSocketIO!=="function")return;var io=new WebSocketIO;if(typeof setting.websocket==="string")io.url=setting.websocket;io.session=self.session;return io.connect()}()||function(){if(typeof CometIO!=="function")return;var io=new CometIO;if(typeof setting.comet==="string")io.url=setting.comet;io.session=self.session;return io.connect()}();if(typeof self.io==="undefined"){setTimeout(function(){self.emit("error","WebSocketIO and CometIO are not available")},100);return self}if(self.io.url.match(/^ws:\/\/.+/))self.type="websocket";else if(self.io.url.match(/cometio/))self.type="comet";else self.type="unknown";self.io.on("*",function(event_name,args){if(event_name==="connect")event_name="__connect";self.emit(event_name,args)});ws_close_timer=setTimeout(function(){self.close();self.type="comet";connect_io()},3e3);self.once("connect",function(){if(ws_close_timer)clearTimeout(ws_close_timer);ws_close_timer=null});return self};this.close=function(){self.io.close()};this.push=function(type,data){self.io.push(type,data)}};var CometIO=function(url,opts){(new EventEmitter).apply(this);if(typeof opts==="undefined"||opts===null)opts={};this.url=url||"";this.session=opts.session||null;var running=false;var self=this;var post_queue=[];var flush=function(){if(!running||post_queue.length<1)return;var post_data={json:JSON.stringify({session:self.session,events:post_queue})};$.ajax({url:self.url,data:post_data,success:function(data){},error:function(req,stat,e){self.emit("error","CometIO push error")},complete:function(e){},type:"POST",dataType:"json",timeout:1e4});post_queue=[]};setInterval(flush,1e3);this.push=function(type,data){if(!running||!self.session){self.emit("error","CometIO not connected");return}post_queue.push({type:type,data:data})};this.connect=function(){if(running)return self;self.on("__session_id",function(session){self.session=session;self.emit("connect",self.session)});running=true;get();return self};this.close=function(){running=false;self.removeListener("__session_id")};var get=function(){if(!running)return;$.ajax({url:self.url+"?"+(new Date-0),data:{session:self.session},success:function(data_arr){if(data_arr!==null&&typeof data_arr=="object"&&!!data_arr.length){for(var i=0;i<data_arr.length;i++){var data=data_arr[i];if(data)self.emit(data.type,data.data)}}get()},error:function(req,stat,e){self.emit("error","CometIO get error");setTimeout(get,1e4)},complete:function(e){},type:"GET",dataType:"json",timeout:13e4})}};var WebSocketIO=function(url,opts){(new EventEmitter).apply(this);if(typeof opts==="undefined"||opts===null)opts={};this.url=url||"";this.session=opts.session||null;this.websocket=null;this.connecting=false;var reconnect_timer_id=null;var running=false;var self=this;self.on("__session_id",function(session_id){self.session=session_id;self.emit("connect",self.session)});this.connect=function(){if(typeof WebSocket==="undefined"){self.emit("error","websocket not exists in this browser");return null}self.running=true;var url=self.session?self.url+"/session="+self.session:self.url;self.websocket=new WebSocket(url);self.websocket.onmessage=function(e){var data_=null;try{data_=JSON.parse(e.data)}catch(e){self.emit("error","WebSocketIO data parse error")}if(!!data_)self.emit(data_.type,data_.data)};self.websocket.onclose=function(){if(self.connecting){self.connecting=false;self.emit("disconnect")}if(self.running){reconnect_timer_id=setTimeout(self.connect,1e4)}};self.websocket.onopen=function(){self.connecting=true};return self};this.close=function(){clearTimeout(reconnect_timer_id);self.running=false;self.websocket.close()};this.push=function(type,data){if(!self.connecting){self.emit("error","websocket not connected");return}self.websocket.send(JSON.stringify({type:type,data:data,session:self.session}))}};var EventEmitter=function(){var self=this;this.apply=function(target,prefix){if(!prefix)prefix="";for(var func in self){if(self.hasOwnProperty(func)&&func!=="apply"){target[prefix+func]=this[func]}}};this.__events=new Array;this.on=function(type,listener,opts){if(typeof listener!=="function")return;var event_id=self.__events.length>0?1+self.__events[self.__events.length-1].id:0;var params={id:event_id,type:type,listener:listener};for(i in opts){if(!params[i])params[i]=opts[i]}self.__events.push(params);return event_id};this.once=function(type,listener){self.on(type,listener,{once:true})};this.emit=function(type,data){for(var i=0;i<self.__events.length;i++){var e=self.__events[i];switch(e.type){case type:e.listener(data);if(e.once)e.type=null;break;case"*":e.listener(type,data);if(e.once)e.type=null;break}}self.removeListener()};this.removeListener=function(id_or_type){for(var i=self.__events.length-1;i>=0;i--){var e=self.__events[i];switch(typeof id_or_type){case"number":if(e.id===id_or_type)self.__events.splice(i,1);break;case"string":case"object":if(e.type===id_or_type)self.__events.splice(i,1);break}}}};if(typeof module!=="undefined"&&typeof module.exports!=="undefined"){module.exports=EventEmitter}
|
@@ -7,10 +7,10 @@ linda = Sinatra::RocketIO::Linda::Client.new 'http://localhost:5000'
|
|
7
7
|
ts = linda.tuplespace["calc"]
|
8
8
|
|
9
9
|
calc = lambda{
|
10
|
-
ts.take ["calc_request"] do |tuple|
|
10
|
+
ts.take ["calc_request"] do |tuple, info|
|
11
11
|
query = tuple[1]
|
12
12
|
result = eval(query)
|
13
|
-
puts "calc: #{query} = #{result}"
|
13
|
+
puts "calc: #{query} = #{result} (from:#{info.from})"
|
14
14
|
ts.write ["calc_result", result]
|
15
15
|
calc.call
|
16
16
|
end
|
data/sample/public/client.js
CHANGED
data/sample/public/worker.js
CHANGED
@@ -2,7 +2,7 @@ var linda = new Linda();
|
|
2
2
|
var ts = new linda.TupleSpace("calc");
|
3
3
|
|
4
4
|
var calc = function(){
|
5
|
-
ts.take(["calc_request"], function(tuple){
|
5
|
+
ts.take(["calc_request"], function(tuple, info){
|
6
6
|
var query = tuple[1];
|
7
7
|
var result = eval(query);
|
8
8
|
$("#log").prepend( $("<p>").text(query+" = "+result).prepend("calc: ") );
|
@@ -26,7 +26,7 @@ Gem::Specification.new do |spec|
|
|
26
26
|
|
27
27
|
spec.add_dependency "linda", ">= 0.0.4"
|
28
28
|
spec.add_dependency "hashie"
|
29
|
-
spec.add_dependency "sinatra-rocketio"
|
29
|
+
spec.add_dependency "sinatra-rocketio", "~> 0.3"
|
30
30
|
spec.add_dependency "event_emitter"
|
31
31
|
spec.add_dependency "sinatra"
|
32
32
|
spec.add_dependency "args_parser"
|
@@ -15,16 +15,16 @@ class TestClientDisconnect < MiniTest::Test
|
|
15
15
|
client2.io.on :connect do
|
16
16
|
ts1 = client1.tuplespace[ts_name]
|
17
17
|
ts2 = client2.tuplespace[ts_name]
|
18
|
-
ts1.read [1,2] do |tuple|
|
18
|
+
ts1.read [1,2] do |tuple, info|
|
19
19
|
_tuple1 = tuple
|
20
20
|
end
|
21
|
-
ts1.take [1,2] do |tuple|
|
21
|
+
ts1.take [1,2] do |tuple, info|
|
22
22
|
_tuple2 = tuple
|
23
23
|
end
|
24
|
-
ts1.watch [1,2] do |tuple|
|
24
|
+
ts1.watch [1,2] do |tuple, info|
|
25
25
|
_tuple3 = tuple
|
26
26
|
end
|
27
|
-
ts2.take [1,2] do |tuple|
|
27
|
+
ts2.take [1,2] do |tuple, info|
|
28
28
|
_tuple4 = tuple
|
29
29
|
end
|
30
30
|
client1.io.close
|
data/test/test_rubyclient.rb
CHANGED
@@ -18,19 +18,19 @@ class TestRubyClient < MiniTest::Test
|
|
18
18
|
ts.write ["rw",1,2,3]
|
19
19
|
ts.write ["rw",1,2,"a"]
|
20
20
|
ts.write ["rw",1,"a",2]
|
21
|
-
ts.take ["rw",1,2] do |tuple|
|
21
|
+
ts.take ["rw",1,2] do |tuple, info|
|
22
22
|
_tuple1 = tuple
|
23
23
|
end
|
24
|
-
ts.read ["rw",1,2] do |tuple|
|
24
|
+
ts.read ["rw",1,2] do |tuple, info|
|
25
25
|
_tuple2 = tuple
|
26
26
|
end
|
27
|
-
ts.take ["rw",1,2] do |tuple|
|
27
|
+
ts.take ["rw",1,2] do |tuple, info|
|
28
28
|
_tuple3 = tuple
|
29
29
|
end
|
30
30
|
client2 = Sinatra::RocketIO::Linda::Client.new App.url
|
31
31
|
ts2 = client2.tuplespace[ts_name]
|
32
32
|
client2.io.on :connect do
|
33
|
-
ts2.take ["rw",1] do |tuple|
|
33
|
+
ts2.take ["rw",1] do |tuple, info|
|
34
34
|
_tuple4 = tuple
|
35
35
|
end
|
36
36
|
end
|
@@ -51,13 +51,13 @@ class TestRubyClient < MiniTest::Test
|
|
51
51
|
_tuple2 = nil
|
52
52
|
ts = @client.tuplespace["ts_#{rand Time.now.to_i}"]
|
53
53
|
@client.io.on :connect do
|
54
|
-
ts.take ["watch",1,2] do |tuple|
|
54
|
+
ts.take ["watch",1,2] do |tuple, info|
|
55
55
|
_tuple1 = tuple
|
56
56
|
end
|
57
|
-
ts.read ["watch",1,2] do |tuple|
|
57
|
+
ts.read ["watch",1,2] do |tuple, info|
|
58
58
|
_tuple2 = tuple
|
59
59
|
end
|
60
|
-
ts.watch ["watch",1,2] do |tuple|
|
60
|
+
ts.watch ["watch",1,2] do |tuple, info|
|
61
61
|
results.push tuple
|
62
62
|
end
|
63
63
|
ts.write ["watch",1,2,3]
|
@@ -81,10 +81,10 @@ class TestRubyClient < MiniTest::Test
|
|
81
81
|
_tuple1 = nil
|
82
82
|
_tuple2 = nil
|
83
83
|
@client.io.on :connect do
|
84
|
-
ts2.take ["a"] do |tuple|
|
84
|
+
ts2.take ["a"] do |tuple, info|
|
85
85
|
_tuple2 = tuple
|
86
86
|
end
|
87
|
-
ts1.take [1] do |tuple|
|
87
|
+
ts1.take [1] do |tuple, info|
|
88
88
|
_tuple1 = tuple
|
89
89
|
end
|
90
90
|
ts1.write [1,2,3]
|
@@ -106,12 +106,12 @@ class TestRubyClient < MiniTest::Test
|
|
106
106
|
ts.write ["expire",1,2,999], :expire => false
|
107
107
|
ts.write ["expire",1,2,3], :expire => 10
|
108
108
|
ts.write ["expire",1,2,"a","b"], :expire => 2
|
109
|
-
ts.read ["expire",1,2] do |tuple|
|
109
|
+
ts.read ["expire",1,2] do |tuple, info|
|
110
110
|
_tuple1 = tuple
|
111
111
|
end
|
112
112
|
sleep 3
|
113
113
|
push :check_expire, nil
|
114
|
-
ts.read ["expire",1,2] do |tuple|
|
114
|
+
ts.read ["expire",1,2] do |tuple, info|
|
115
115
|
_tuple2 = tuple
|
116
116
|
end
|
117
117
|
end
|
@@ -122,4 +122,39 @@ class TestRubyClient < MiniTest::Test
|
|
122
122
|
assert_equal _tuple1, ["expire",1,2,"a","b"]
|
123
123
|
assert_equal _tuple2, ["expire",1,2,3]
|
124
124
|
end
|
125
|
+
|
126
|
+
def test_tuple_info
|
127
|
+
ts = @client.tuplespace["ts_#{rand Time.now.to_i}"]
|
128
|
+
_tuple1 = nil
|
129
|
+
_tuple2 = nil
|
130
|
+
_tuple3 = nil
|
131
|
+
_info1 = nil
|
132
|
+
_info2 = nil
|
133
|
+
_info3 = nil
|
134
|
+
@client.io.on :connect do
|
135
|
+
ts.read [1,2] do |tuple, info|
|
136
|
+
_tuple1 = tuple
|
137
|
+
_info1 = info
|
138
|
+
end
|
139
|
+
ts.watch [1] do |tuple, info|
|
140
|
+
_tuple2 = tuple
|
141
|
+
_info2 = info
|
142
|
+
end
|
143
|
+
ts.take [1,2,3] do |tuple, info|
|
144
|
+
_tuple3 = tuple
|
145
|
+
_info3 = info
|
146
|
+
end
|
147
|
+
ts.write [1,2,3]
|
148
|
+
end
|
149
|
+
50.times do
|
150
|
+
sleep 0.1
|
151
|
+
break if _tuple3
|
152
|
+
end
|
153
|
+
assert_equal _tuple1, [1,2,3]
|
154
|
+
assert_equal _tuple2, [1,2,3]
|
155
|
+
assert_equal _tuple3, [1,2,3]
|
156
|
+
assert _info1.from =~ /^\d+\.\d+\.\d+\.\d+$/
|
157
|
+
assert _info2.from =~ /^\d+\.\d+\.\d+\.\d+$/
|
158
|
+
assert _info3.from =~ /^\d+\.\d+\.\d+\.\d+$/
|
159
|
+
end
|
125
160
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sinatra-rocketio-linda
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sho Hashimoto
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-
|
11
|
+
date: 2013-10-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -112,16 +112,16 @@ dependencies:
|
|
112
112
|
name: sinatra-rocketio
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
114
114
|
requirements:
|
115
|
-
- -
|
115
|
+
- - ~>
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version: '0'
|
117
|
+
version: '0.3'
|
118
118
|
type: :runtime
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
|
-
- -
|
122
|
+
- - ~>
|
123
123
|
- !ruby/object:Gem::Version
|
124
|
-
version: '0'
|
124
|
+
version: '0.3'
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
126
|
name: event_emitter
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -231,7 +231,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
231
231
|
version: '0'
|
232
232
|
requirements: []
|
233
233
|
rubyforge_project:
|
234
|
-
rubygems_version: 2.
|
234
|
+
rubygems_version: 2.1.5
|
235
235
|
signing_key:
|
236
236
|
specification_version: 4
|
237
237
|
summary: Linda implementation on Sinatra RocketIO
|
@@ -244,4 +244,3 @@ test_files:
|
|
244
244
|
- test/test_rubyclient.rb
|
245
245
|
- test/test_tuple.rb
|
246
246
|
- test/test_tuplespace.rb
|
247
|
-
has_rdoc:
|