sinatra-rocketio-linda 0.2.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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:
|