sinatra-rocketio-linda 0.0.2 → 0.0.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ebfcd893b6fd6ef33fa0c366cb796c70896b76f2
4
- data.tar.gz: 85c84d5d7b420570cf6ed9a806dd2c94e2ea42ab
3
+ metadata.gz: 22a5549a8d89eeae678b0f22d44dae2afad0473f
4
+ data.tar.gz: aa42150b15eb7393de375740260e094c60e8ce00
5
5
  SHA512:
6
- metadata.gz: d2f78eeef9f0237a405a87684b7d832a986dcafa6b3aad4194036190efeef7859af3b811c72783820294d1bccd7826e13b9f6d0b9df2a0c78b8f833a66c9b47b
7
- data.tar.gz: a73311f2263b81720aa7c6963af7ea7e8eaf1b590637dfd43184da1409c7486dd613ec835d0bbec666d8ed65feb222154f418518985ae50262087ecaf588f2ff
6
+ metadata.gz: 5ce242560eb393dd968e79199708a6a7c5f1cce9a8593015d1f89b88286ee26ecb9f3d7f4aea5efc9856386ca5cdf39c255b2fe3f0a00793ca6940a369259111
7
+ data.tar.gz: 8f71b0aefc032cd9b2020a365b6633a95e7307817417ba4df96d2304a70a4b120d75544e43293f0e5a6fedd1418e5c646e16c655d6b1fa286088933665f6cab5
@@ -1,8 +1,16 @@
1
+ === 0.0.3 2013-05-16
2
+
3
+ * remove read/take/watch listener on client disconnect
4
+ * {expire => false} option on tuple write
5
+ * add ruby client's test
6
+
1
7
  === 0.0.2 2013-05-15
8
+
2
9
  * update README
3
10
  * TupleSpace#watch(tuple, callback(tuple))
4
11
 
5
12
  === 0.0.1 2013-05-15
13
+
6
14
  * JavaScript Linda Client for WebBrowser
7
15
  * Ruby Linda Client
8
16
  * TupleSpace#write(tuple)
data/README.md CHANGED
@@ -54,7 +54,7 @@ Server Side
54
54
  require 'sinatra'
55
55
  require 'sinatra/rocketio'
56
56
  require 'sinatra/rocketio/linda'
57
- set :linda, :check_expire => 60
57
+ set :linda, :expire_check => 60
58
58
 
59
59
  run Sinatra::Application
60
60
  ```
@@ -151,6 +151,13 @@ Test
151
151
 
152
152
  % gem install bundler
153
153
  % bundle install
154
+
155
+ start server
156
+
157
+ % rake test_server
158
+
159
+ run test
160
+
154
161
  % rake test
155
162
 
156
163
 
data/Rakefile CHANGED
@@ -5,4 +5,10 @@ Rake::TestTask.new do |t|
5
5
  t.pattern = "test/test_*.rb"
6
6
  end
7
7
 
8
+ desc "Start test server"
9
+ task :test_server do
10
+ require File.expand_path 'test/app', File.dirname(__FILE__)
11
+ App.start
12
+ end
13
+
8
14
  task :default => :test
@@ -3,22 +3,26 @@ module Sinatra
3
3
  module Linda
4
4
 
5
5
  def self.tuplespaces
6
- @@spaces ||= Hash.new{|h,k| h[k] = TupleSpace.new }
6
+ @@spaces ||= Hash.new{|h,k| h[k] = TupleSpace.new(k) }
7
7
  end
8
8
 
9
9
  def self.[](name)
10
10
  self.tuplespaces[name]
11
11
  end
12
12
 
13
+ def self.check_expire
14
+ tuplespaces.values.each do |ts|
15
+ ts.check_expire
16
+ end
17
+ end
18
+
13
19
  end
14
20
  end
15
21
  end
16
22
 
17
23
  Sinatra::RocketIO.on :start do
18
24
  EM::add_periodic_timer Sinatra::RocketIO::Linda.options[:expire_check] do
19
- Sinatra::RocketIO::Linda::tuplespaces.values.each do |ts|
20
- ts.check_expire
21
- end
25
+ Sinatra::RocketIO::Linda.check_expire
22
26
  end
23
27
  end
24
28
 
@@ -43,50 +47,23 @@ Sinatra::RocketIO.on :__linda_write do |data, client|
43
47
  Sinatra::RocketIO::Linda[space].write tuple, opts
44
48
  end
45
49
 
46
- Sinatra::RocketIO.on :__linda_read do |data, client|
47
- space, tuple, callback = data
48
- space = "__default__" if !space or !space.kind_of? String or space.empty?
49
- unless [Hash, Array].include? tuple.class
50
- Sinatra::RocketIO::Linda.emit :error, "received Tuple is not Hash or Array at :__linda_read"
51
- next
52
- end
53
- if !callback or !callback.kind_of? String or callback.empty?
54
- Sinatra::RocketIO::Linda.emit :error, "received Callback ID is not valid at :__linda_read"
55
- next
56
- end
57
- Sinatra::RocketIO::Linda[space].read tuple do |tuple|
58
- Sinatra::RocketIO.push "__linda_read_callback_#{callback}", tuple.data, :to => client.session
59
- end
60
- end
61
-
62
- Sinatra::RocketIO.on :__linda_take do |data, client|
63
- space, tuple, callback = data
64
- space = "__default__" if !space or !space.kind_of? String or space.empty?
65
- unless [Hash, Array].include? tuple.class
66
- Sinatra::RocketIO::Linda.emit :error, "received Tuple is not Hash or Array at :__linda_take"
67
- next
68
- end
69
- if !callback or !callback.kind_of? String or callback.empty?
70
- Sinatra::RocketIO::Linda.emit :error, "received Callback ID is not valid at :__linda_take"
71
- next
72
- end
73
- Sinatra::RocketIO::Linda[space].take tuple do |tuple|
74
- Sinatra::RocketIO.push "__linda_take_callback_#{callback}", tuple.data, :to => client.session
75
- end
76
- end
77
-
78
- Sinatra::RocketIO.on :__linda_watch do |data, client|
79
- space, tuple, callback = data
80
- space = "__default__" if !space or !space.kind_of? String or space.empty?
81
- unless [Hash, Array].include? tuple.class
82
- Sinatra::RocketIO::Linda.emit :error, "received Tuple is not Hash or Array at :__linda_watch"
83
- next
84
- end
85
- if !callback or !callback.kind_of? String or callback.empty?
86
- Sinatra::RocketIO::Linda.emit :error, "received Callback ID is not valid at :__linda_watch"
87
- next
88
- end
89
- Sinatra::RocketIO::Linda[space].watch tuple do |tuple|
90
- Sinatra::RocketIO.push "__linda_watch_callback_#{callback}", tuple.data, :to => client.session
50
+ [:read, :take, :watch].each do |func|
51
+ Sinatra::RocketIO.on "__linda_#{func}" do |data, client|
52
+ space, tuple, callback = data
53
+ space = "__default__" if !space or !space.kind_of? String or space.empty?
54
+ unless [Hash, Array].include? tuple.class
55
+ Sinatra::RocketIO::Linda.emit :error, "received Tuple is not Hash or Array at :__linda_#{func}"
56
+ next
57
+ end
58
+ if !callback or !callback.kind_of? String or callback.empty?
59
+ Sinatra::RocketIO::Linda.emit :error, "received Callback ID is not valid at :__linda_#{func}"
60
+ next
61
+ end
62
+ eid = Sinatra::RocketIO::Linda[space].__send__ func, tuple do |tuple|
63
+ Sinatra::RocketIO.push "__linda_#{func}_callback_#{callback}", tuple.data, :to => client.session
64
+ end
65
+ Sinatra::RocketIO.on :disconnect do |_client|
66
+ Sinatra::RocketIO::Linda[space].remove_callback eid if client.session == _client.session
67
+ end
91
68
  end
92
69
  end
@@ -10,7 +10,9 @@ module Sinatra
10
10
  end
11
11
  @data = data
12
12
  @type = data.class
13
- @expire_at = Time.now+(opts[:expire] || 300)
13
+ if opts[:expire].class == Fixnum and opts[:expire] > 0
14
+ @expire_at = Time.now + opts[:expire]
15
+ end
14
16
  end
15
17
 
16
18
  def match?(target)
@@ -4,8 +4,10 @@ module Sinatra
4
4
 
5
5
  class TupleSpace
6
6
  include Enumerable
7
+ attr_reader :name
7
8
 
8
- def initialize
9
+ def initialize(name="__default__")
10
+ @name = name
9
11
  @tuples = Array.new
10
12
  @callbacks = Array.new
11
13
  end
@@ -16,6 +18,10 @@ module Sinatra
16
18
  end
17
19
  end
18
20
 
21
+ def remove_callback(callback)
22
+ @callbacks.delete callback
23
+ end
24
+
19
25
  def size
20
26
  @tuples.size
21
27
  end
@@ -60,7 +66,11 @@ module Sinatra
60
66
  end
61
67
  end
62
68
  end
63
- @callbacks.push(:type => :read, :callback => block, :tuple => tuple) if block_given?
69
+ if block_given?
70
+ callback = {:type => :read, :callback => block, :tuple => tuple}
71
+ @callbacks.push callback
72
+ return callback
73
+ end
64
74
  end
65
75
 
66
76
  def take(tuple, &block)
@@ -80,20 +90,26 @@ module Sinatra
80
90
  return matched_tuple
81
91
  end
82
92
  else
83
- @callbacks.push(:type => :take, :callback => block, :tuple => tuple) if block_given?
93
+ if block_given?
94
+ callback = {:type => :take, :callback => block, :tuple => tuple}
95
+ @callbacks.push callback
96
+ return callback
97
+ end
84
98
  end
85
99
  end
86
100
 
87
101
  def watch(tuple, &block)
88
102
  raise ArgumentError, "block not given" unless block_given?
89
103
  tuple = Tuple.new tuple unless tuple.kind_of? Tuple
90
- @callbacks.unshift(:type => :watch, :callback => block, :tuple => tuple)
104
+ callback = {:type => :watch, :callback => block, :tuple => tuple}
105
+ @callbacks.unshift callback
106
+ callback
91
107
  end
92
108
 
93
109
  def check_expire
94
110
  expires = []
95
- each do |tuple|
96
- expires.push tuple unless tuple.expire_at > Time.now
111
+ self.each do |tuple|
112
+ expires.push(tuple) if tuple.expire_at and tuple.expire_at < Time.now
97
113
  end
98
114
  expires.each do |tuple|
99
115
  @tuples.delete tuple
@@ -1,7 +1,7 @@
1
1
  module Sinatra
2
2
  module RocketIO
3
3
  module Linda
4
- VERSION = "0.0.2"
4
+ VERSION = "0.0.3"
5
5
  end
6
6
  end
7
7
  end
@@ -0,0 +1,38 @@
1
+ class App
2
+
3
+ def self.running
4
+ @running ? true : false
5
+ end
6
+
7
+ def self.port
8
+ ENV['PORT'] || 5000
9
+ end
10
+
11
+ def self.ws_port
12
+ ENV['WS_PORT'] || 5001
13
+ end
14
+
15
+ def self.url
16
+ "http://localhost:#{port}"
17
+ end
18
+
19
+ def self.websocketio_url
20
+ "ws://localhost:#{ws_port}"
21
+ end
22
+
23
+ def self.cometio_url
24
+ "http://localhost:#{port}/cometio/io"
25
+ end
26
+
27
+ def self.app_dir
28
+ File.expand_path 'app', File.dirname(__FILE__)
29
+ end
30
+
31
+ def self.start
32
+ return if running
33
+ @running = true
34
+ cmd = "cd #{app_dir} && WS_PORT=#{ws_port} rackup config.ru -p #{port}"
35
+ system cmd
36
+ end
37
+
38
+ end
@@ -0,0 +1,14 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ require 'sinatra'
4
+ require 'sinatra/base'
5
+ $stdout.sync = true
6
+ $:.unshift File.expand_path '../../lib', File.dirname(__FILE__)
7
+ require 'sinatra/rocketio'
8
+ require 'sinatra/rocketio/linda'
9
+ require File.dirname(__FILE__)+'/main'
10
+
11
+ set :linda, :expire_check => 30
12
+ set :websocketio, :port => ENV['WS_PORT'].to_i
13
+
14
+ run TestApp
@@ -0,0 +1,28 @@
1
+ class TestApp < Sinatra::Base
2
+ register Sinatra::RocketIO
3
+ io = Sinatra::RocketIO
4
+ register Sinatra::RocketIO::Linda
5
+ linda = Sinatra::RocketIO::Linda
6
+
7
+ get '/' do
8
+ "sinatra-rocketio-linda v#{Sinatra::RocketIO::Linda::VERSION}"
9
+ end
10
+
11
+ io.on :connect do |client|
12
+ puts "new client <session:#{client.session}> <type:#{client.type}>"
13
+ end
14
+
15
+ io.on :disconnect do |client|
16
+ puts "disconnect client <session:#{client.session}> <type:#{client.type}>"
17
+ end
18
+
19
+ io.on :check_expire do |data, client|
20
+ puts "check_expire"
21
+ linda.check_expire
22
+ end
23
+
24
+ io.on :* do |event, data, client|
25
+ next unless event.to_s =~ /linda/
26
+ puts "#{event} - #{data} from #{client}"
27
+ end
28
+ end
@@ -0,0 +1,46 @@
1
+ require File.expand_path 'test_helper', File.dirname(__FILE__)
2
+ require 'sinatra/rocketio/linda/client'
3
+
4
+ class TestClientDisconnect < MiniTest::Test
5
+
6
+ def test_client_disconnect
7
+ ts_name = "ts_#{Time.now.to_i}_#{Time.now.usec}"
8
+ client1 = Sinatra::RocketIO::Linda::Client.new App.url
9
+ _tuple1 = nil
10
+ _tuple2 = nil
11
+ _tuple3 = nil
12
+ _tuple4 = nil
13
+ client1.io.on :connect do
14
+ client2 = Sinatra::RocketIO::Linda::Client.new App.url
15
+ client2.io.on :connect do
16
+ ts1 = client1.tuplespace[ts_name]
17
+ ts2 = client2.tuplespace[ts_name]
18
+ ts1.read [1,2] do |tuple|
19
+ _tuple1 = tuple
20
+ end
21
+ ts1.take [1,2] do |tuple|
22
+ _tuple2 = tuple
23
+ end
24
+ ts1.watch [1,2] do |tuple|
25
+ _tuple3 = tuple
26
+ end
27
+ ts2.take [1,2] do |tuple|
28
+ _tuple4 = tuple
29
+ end
30
+ client1.io.close
31
+ sleep 3
32
+ ts2.write [1,2,3]
33
+ ts2.write [1,2,3,4]
34
+ end
35
+ end
36
+ 50.times do
37
+ sleep 0.1
38
+ break if _tuple4
39
+ end
40
+ assert_equal _tuple1, nil
41
+ assert_equal _tuple2, nil
42
+ assert_equal _tuple3, nil
43
+ assert_equal _tuple4, [1,2,3]
44
+ end
45
+
46
+ end
@@ -1,3 +1,5 @@
1
1
  require 'rubygems'
2
+ require 'bundler/setup'
2
3
  require 'minitest/autorun'
4
+ require File.expand_path 'app', File.dirname(__FILE__)
3
5
  $:.unshift File.expand_path '../lib', File.dirname(__FILE__)
@@ -0,0 +1,125 @@
1
+ require File.expand_path 'test_helper', File.dirname(__FILE__)
2
+ require 'sinatra/rocketio/linda/client'
3
+
4
+ class TestRubyClient < MiniTest::Test
5
+
6
+ def setup
7
+ @client = Sinatra::RocketIO::Linda::Client.new App.url
8
+ end
9
+
10
+ def test_write_read_take
11
+ ts_name = "ts_#{rand Time.now.to_i}"
12
+ ts = @client.tuplespace[ts_name]
13
+ _tuple1 = nil
14
+ _tuple2 = nil
15
+ _tuple3 = nil
16
+ _tuple4 = nil
17
+ @client.io.on :connect do
18
+ ts.write ["rw",1,2,3]
19
+ ts.write ["rw",1,2,"a"]
20
+ ts.write ["rw",1,"a",2]
21
+ ts.take ["rw",1,2] do |tuple|
22
+ _tuple1 = tuple
23
+ end
24
+ ts.read ["rw",1,2] do |tuple|
25
+ _tuple2 = tuple
26
+ end
27
+ ts.take ["rw",1,2] do |tuple|
28
+ _tuple3 = tuple
29
+ end
30
+ client2 = Sinatra::RocketIO::Linda::Client.new App.url
31
+ ts2 = client2.tuplespace[ts_name]
32
+ client2.io.on :connect do
33
+ ts2.take ["rw",1] do |tuple|
34
+ _tuple4 = tuple
35
+ end
36
+ end
37
+ end
38
+ 50.times do
39
+ sleep 0.1
40
+ break if _tuple4
41
+ end
42
+ assert_equal _tuple1, ["rw",1,2,"a"] # take
43
+ assert_equal _tuple2, ["rw",1,2,3] # read
44
+ assert_equal _tuple3, ["rw",1,2,3] # take
45
+ assert_equal _tuple4, ["rw",1,"a",2]
46
+ end
47
+
48
+ def test_watch
49
+ results = []
50
+ _tuple1 = nil
51
+ _tuple2 = nil
52
+ ts = @client.tuplespace["ts_#{rand Time.now.to_i}"]
53
+ @client.io.on :connect do
54
+ ts.take ["watch",1,2] do |tuple|
55
+ _tuple1 = tuple
56
+ end
57
+ ts.read ["watch",1,2] do |tuple|
58
+ _tuple2 = tuple
59
+ end
60
+ ts.watch ["watch",1,2] do |tuple|
61
+ results.push tuple
62
+ end
63
+ ts.write ["watch",1,2,3]
64
+ ts.write ["watch",1,"a",2]
65
+ ts.write ["watch",1,2,3,4]
66
+ end
67
+ 50.times do
68
+ sleep 0.1
69
+ break if _tuple1 != nil and _tuple2 != nil
70
+ end
71
+ assert_equal _tuple1, ["watch",1,2,3]
72
+ assert_equal _tuple2, ["watch",1,2,3,4]
73
+ assert_equal results.size, 2
74
+ assert_equal results[0], ["watch",1,2,3]
75
+ assert_equal results[1], ["watch",1,2,3,4]
76
+ end
77
+
78
+ def test_tuplespaces
79
+ ts1 = @client.tuplespace["ts1_#{rand Time.now.to_i}"]
80
+ ts2 = @client.tuplespace["ts2_#{rand Time.now.to_i}"]
81
+ _tuple1 = nil
82
+ _tuple2 = nil
83
+ @client.io.on :connect do
84
+ ts2.take ["a"] do |tuple|
85
+ _tuple2 = tuple
86
+ end
87
+ ts1.take [1] do |tuple|
88
+ _tuple1 = tuple
89
+ end
90
+ ts1.write [1,2,3]
91
+ ts2.write ["a","b","c"]
92
+ end
93
+ 50.times do
94
+ sleep 0.1
95
+ break if _tuple1
96
+ end
97
+ assert_equal _tuple1, [1,2,3]
98
+ assert_equal _tuple2, ["a","b","c"]
99
+ end
100
+
101
+ def test_tuple_expire
102
+ ts = @client.tuplespace["ts_#{rand Time.now.to_i}"]
103
+ _tuple1 = nil
104
+ _tuple2 = nil
105
+ @client.io.on :connect do
106
+ ts.write ["expire",1,2,999], :expire => false
107
+ ts.write ["expire",1,2,3], :expire => 10
108
+ ts.write ["expire",1,2,"a","b"], :expire => 2
109
+ ts.read ["expire",1,2] do |tuple|
110
+ _tuple1 = tuple
111
+ end
112
+ sleep 3
113
+ @client.io.push :check_expire, []
114
+ ts.read ["expire",1,2] do |tuple|
115
+ _tuple2 = tuple
116
+ end
117
+ end
118
+ 50.times do
119
+ sleep 0.1
120
+ break if _tuple2
121
+ end
122
+ assert_equal _tuple1, ["expire",1,2,"a","b"]
123
+ assert_equal _tuple2, ["expire",1,2,3]
124
+ end
125
+ end
@@ -117,13 +117,17 @@ class TestTupleSpace < MiniTest::Test
117
117
  end
118
118
 
119
119
  def test_tuple_expire
120
+ @space.write [1,2,999], :expire => false
120
121
  @space.write [1,2,3], :expire => 3
121
122
  @space.write [1,2,"a","b"], :expire => 2
122
- assert_equal @space.size, 2
123
+ assert_equal @space.size, 3
123
124
  sleep 2
124
125
  @space.check_expire
125
- assert_equal @space.size, 1
126
+ assert_equal @space.size, 2
126
127
  assert_equal @space.take([1,2]).data, [1,2,3]
128
+ assert_equal @space.size, 1
129
+ sleep 1
130
+ assert_equal @space.take([1,2]).data, [1,2,999]
127
131
  assert_equal @space.size, 0
128
132
  end
129
133
 
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.0.2
4
+ version: 0.0.3
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-05-15 00:00:00.000000000 Z
11
+ date: 2013-05-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -156,7 +156,12 @@ files:
156
156
  - sample/views/index.haml
157
157
  - sample/views/worker.haml
158
158
  - sinatra-rocketio-linda.gemspec
159
+ - test/app.rb
160
+ - test/app/config.ru
161
+ - test/app/main.rb
162
+ - test/test_client_disconnect.rb
159
163
  - test/test_helper.rb
164
+ - test/test_rubyclient.rb
160
165
  - test/test_tuple.rb
161
166
  - test/test_tuplespace.rb
162
167
  homepage: https://github.com/shokai/sinatra-rocketio-linda
@@ -184,6 +189,11 @@ signing_key:
184
189
  specification_version: 4
185
190
  summary: Linda implementation on Sinatra RocketIO
186
191
  test_files:
192
+ - test/app.rb
193
+ - test/app/config.ru
194
+ - test/app/main.rb
195
+ - test/test_client_disconnect.rb
187
196
  - test/test_helper.rb
197
+ - test/test_rubyclient.rb
188
198
  - test/test_tuple.rb
189
199
  - test/test_tuplespace.rb