sinatra-rocketio-linda 0.0.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 523bf63e3fe852d759d5e75b62e82d8b5900ffa9
4
+ data.tar.gz: ca656ff542d98f73c942542ddeaf5654566f5b60
5
+ SHA512:
6
+ metadata.gz: 6328614db8c10c14410d515d7aad2a0885335165e4aaeae081852fae8dd13cf45687cf4ae30e6caf571a8b2d5cca7b08434d8387b962bf30f350c3a83290792f
7
+ data.tar.gz: 0f41f574bbcace16a210b0f4e3a93f29d0aca235ae1dd3e9b85b52f1dd0ffe548a123e125f6cdd87c9d1d3590af7e723c7fe6a2de837c995847f50e1ef3b50c6
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ .ruby-version
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in sinatra-rocketio-linda.gemspec
4
+ gemspec
data/History.txt ADDED
@@ -0,0 +1,8 @@
1
+ === 0.0.1 2013-05-15
2
+
3
+ * JavaScript Linda Client for WebBrowser
4
+ * Ruby Linda Client
5
+ * TupleSpace#write(tuple)
6
+ * TupleSpace#take(tuple, callback(tuple))
7
+ * TupleSpace#read(tuple, callback(tuple))
8
+ * sinatra config - set :linda, :expire_check => 60 (sec)
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Sho Hashimoto
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,117 @@
1
+ sinatra-rocketio-linda
2
+ ======================
3
+
4
+ * Linda implementation on Sinatra::RocketIO
5
+ * https://github.com/shokai/sinatra-rocketio-linda
6
+
7
+
8
+ Linda
9
+ -----
10
+
11
+ * http://en.wikipedia.org/wiki/Linda_(coordination_language)
12
+ * http://ja.wikipedia.org/wiki/Linda
13
+
14
+
15
+ Installation
16
+ ------------
17
+
18
+ % gem install sinatra-rocketio-linda
19
+
20
+
21
+ Requirements
22
+ ------------
23
+ * Ruby 1.8.7 or 1.9.2 or 1.9.3 or 2.0.0
24
+ * Sinatra 1.3.0+
25
+ * [Sinatra RocketIO](https://github.com/shokai/sinatra-rocketio)
26
+ * [EventMachine](http://rubyeventmachine.com)
27
+ * [jQuery](http://jquery.com)
28
+
29
+
30
+ Usage
31
+ -----
32
+
33
+ ### Setup
34
+
35
+ Server Side
36
+
37
+ ```ruby
38
+ require 'sinatra'
39
+ require 'sinatra/rocketio'
40
+ require 'sinatra/rocketio/linda'
41
+ set :linda, :check_expire => 60
42
+
43
+ run Sinatra::Application
44
+ ```
45
+
46
+ Client Side
47
+
48
+ ```html
49
+ <script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
50
+ <script src="<%= rocketio_js %>"></script>
51
+ <script src="<%= linda_js %>"></script>
52
+ ```
53
+
54
+ ```javascript
55
+ var io = new RocketIO().connect();
56
+ var linda = new Linda(io);
57
+ ```
58
+
59
+ ### client / worker
60
+
61
+ client side
62
+
63
+ ```javascript
64
+ // create tuplespace
65
+ var ts = new linda.TupleSpace("calc");
66
+
67
+ // request
68
+ $("#btn_request").click(function(){
69
+ ts.write(["calc_request", "1-2+3*4"]);
70
+ });
71
+
72
+ // wait result
73
+ var take_result = function(){
74
+ ts.take(["calc_result"], function(tuple){
75
+ var result = tuple[1]; // from 'worker' side
76
+ console.log(result);
77
+ take_result(); // recursive call
78
+ });
79
+ };
80
+ io.on("connect", take_result); // RocketIO's "connect" event
81
+ ```
82
+
83
+ worker side
84
+
85
+ ```javascript
86
+ // create tuplespace
87
+ var ts = new linda.TupleSpace("calc");
88
+
89
+ // calculate
90
+ var calc = function(){
91
+ ts.take(["calc_request"], function(tuple){
92
+ var query = tuple[1]; // => "1-2+3*4"
93
+ var result = eval(query);
94
+ console.log(query+" = "+result); // => "1-2+3*4 = 11"
95
+ ts.write(["calc_result", result]); // return to 'client' side
96
+ calc(); // recursive call
97
+ });
98
+ };
99
+ io.on("connect", calc); // RocketIO's "connect" event
100
+ ```
101
+
102
+ Test
103
+ ----
104
+
105
+ % gem install bundler
106
+ % bundle install
107
+ % rake test
108
+
109
+
110
+ Contributing
111
+ ------------
112
+
113
+ 1. Fork it
114
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
115
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
116
+ 4. Push to the branch (`git push origin my-new-feature`)
117
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new do |t|
5
+ t.pattern = "test/test_*.rb"
6
+ end
7
+
8
+ task :default => :test
data/lib/js/linda.js ADDED
@@ -0,0 +1,36 @@
1
+ var Linda = function(io, opts){
2
+ var self = this;
3
+ this.io = null;
4
+ if(io === null || typeof io === "undefined"){
5
+ this.io = new RocketIO().connect();
6
+ }
7
+ else{
8
+ this.io = io;
9
+ }
10
+ this.opts = opts || {};
11
+ this.TupleSpace = function(name){
12
+ if(name === null || typeof name !== "string") name = "__default__";
13
+ this.name = name;
14
+ this.linda = self;
15
+ var space = this;
16
+ this.write = function(tuple, opts){
17
+ if(tuple === null || typeof tuple !== "object") return;
18
+ if(opts === null || typeof opts === "undefined") opts = {};
19
+ self.io.push("__linda_write", [space.name, tuple, opts]);
20
+ };
21
+ this.read = function(tuple, callback){
22
+ if(tuple === null || typeof tuple !== "object") return;
23
+ if(typeof callback !== "function") return;
24
+ var callback_id = new Date()-0+"";
25
+ self.io.once("__linda_read_callback_"+callback_id, callback);
26
+ self.io.push("__linda_read", [space.name, tuple, callback_id]);
27
+ };
28
+ this.take = function(tuple, callback){
29
+ if(tuple === null || typeof tuple !== "object") return;
30
+ if(typeof callback !== "function") return;
31
+ var callback_id = new Date()-0+"";
32
+ self.io.once("__linda_take_callback_"+callback_id, callback);
33
+ self.io.push("__linda_take", [space.name, tuple, callback_id]);
34
+ };
35
+ };
36
+ };
@@ -0,0 +1,16 @@
1
+ module Sinatra
2
+ module RocketIO
3
+ module Linda
4
+
5
+ def self.registered(app)
6
+ app.helpers Sinatra::RocketIO::Linda::Helper
7
+
8
+ app.get '/rocketio/linda.js' do
9
+ content_type 'application/javascript'
10
+ @js ||= ERB.new(::Sinatra::RocketIO::Linda.javascript).result(binding)
11
+ end
12
+ end
13
+
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,13 @@
1
+ module Sinatra
2
+ module RocketIO
3
+ module Linda
4
+ module Helper
5
+
6
+ def linda_js
7
+ "#{env['rack.url_scheme']}://#{env['HTTP_HOST']}#{env['SCRIPT_NAME']}/rocketio/linda.js"
8
+ end
9
+
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,18 @@
1
+ module Sinatra
2
+ module RocketIO
3
+ module Linda
4
+
5
+ def self.javascript(*js_file_names)
6
+ js_file_names = ['linda.js']
7
+ js = ''
8
+ js_file_names.each do |i|
9
+ File.open(File.expand_path "../js/#{i}", File.dirname(__FILE__)) do |f|
10
+ js += f.read+"\n"
11
+ end
12
+ end
13
+ js
14
+ end
15
+
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,76 @@
1
+ module Sinatra
2
+ module RocketIO
3
+ module Linda
4
+
5
+ def self.tuplespaces
6
+ @@spaces ||= Hash.new{|h,k| h[k] = TupleSpace.new }
7
+ end
8
+
9
+ def self.[](name)
10
+ self.tuplespaces[name]
11
+ end
12
+
13
+ end
14
+ end
15
+ end
16
+
17
+ Sinatra::RocketIO.on :start do
18
+ 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
22
+ end
23
+ end
24
+
25
+ EventEmitter.apply Sinatra::RocketIO::Linda
26
+
27
+ Sinatra::RocketIO.on :__linda_write do |data, client|
28
+ space, tuple, opts = data
29
+ space = "__default__" if !space or !space.kind_of? String or space.empty?
30
+ unless [Hash, Array].include? tuple.class
31
+ Sinatra::RocketIO::Linda.emit :error, "received Tuple is not Hash or Array at :__linda_write"
32
+ next
33
+ end
34
+ unless opts.kind_of? Hash
35
+ opts = {}
36
+ else
37
+ opts_ = {}
38
+ opts.each do |k,v|
39
+ opts_[k.to_sym] = v
40
+ end
41
+ opts = opts_
42
+ end
43
+ Sinatra::RocketIO::Linda[space].write tuple, opts
44
+ end
45
+
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
@@ -0,0 +1,53 @@
1
+ module Sinatra
2
+ module RocketIO
3
+ module Linda
4
+
5
+ def linda=(options)
6
+ Linda.options = options
7
+ end
8
+
9
+ def linda
10
+ Linda.options
11
+ end
12
+
13
+ def self.default_options
14
+ {
15
+ :expire_check => [60, lambda{|v| v.kind_of? Fixnum and v > 0 }]
16
+ }
17
+ end
18
+
19
+ def self.options
20
+ @@options ||= (
21
+ opts = {}
22
+ default_options.each do |k,v|
23
+ opts[k] = v[0]
24
+ end
25
+ opts
26
+ )
27
+ end
28
+
29
+ def self.options=(opts)
30
+ @@options = {}
31
+ opts.each do |k,v|
32
+ k = k.to_sym
33
+ unless default_options.include? k
34
+ STDERR.puts "!! Sinatra::RocketIO::Linda setting - \"#{k}\" is not valid key"
35
+ else
36
+ unless default_options[k][1].call(v)
37
+ default = default_options[k][0]
38
+ STDERR.puts "!! Sinatra::RocketIO::Linda setting - \"#{k} => #{v}\" is not valid. set default \"#{k} => #{default}\""
39
+ @@options[k] = default
40
+ else
41
+ @@options[k] = v
42
+ end
43
+ end
44
+ end
45
+ default_options.each do |k, v|
46
+ @@options[k] = v[0] unless @@options.include? k
47
+ end
48
+ @@options
49
+ end
50
+
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,41 @@
1
+ module Sinatra
2
+ module RocketIO
3
+ module Linda
4
+
5
+ class Tuple
6
+ attr_reader :data, :type, :expire_at
7
+ def initialize(data, opts={})
8
+ unless [Array, Hash].include? data.class
9
+ raise ArgumentError, 'argument must be instance of Array or Hash'
10
+ end
11
+ @data = data
12
+ @type = data.class
13
+ @expire_at = Time.now+(opts[:expire] || 300)
14
+ end
15
+
16
+ def match?(target)
17
+ raise ArgumentError, 'argument must be instance of Tuple' unless target.kind_of? self.class
18
+ return false if @type != target.type
19
+ if @type == Array
20
+ return false if @data.length > target.data.length
21
+ @data.each_with_index do |v,i|
22
+ return false if target.data[i] != v
23
+ end
24
+ return true
25
+ elsif @type == Hash
26
+ @data.each do |k,v|
27
+ return false if target.data[k] != v
28
+ end
29
+ return true
30
+ end
31
+ false
32
+ end
33
+
34
+ def to_s
35
+ @data.to_s
36
+ end
37
+ end
38
+
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,100 @@
1
+ module Sinatra
2
+ module RocketIO
3
+ module Linda
4
+
5
+ class TupleSpace
6
+ include Enumerable
7
+
8
+ def initialize
9
+ @tuples = Array.new
10
+ @callbacks = Array.new
11
+ end
12
+
13
+ def each(&block)
14
+ @tuples.each do |tp|
15
+ yield tp
16
+ end
17
+ end
18
+
19
+ def size
20
+ @tuples.size
21
+ end
22
+
23
+ DEFAULT_WRITE_OPTIONS = {
24
+ :expire => 300
25
+ }
26
+
27
+ def write(tuple, opts={})
28
+ raise ArgumentError, "options must be Hash" unless opts.kind_of? Hash
29
+ DEFAULT_WRITE_OPTIONS.each do |k,v|
30
+ opts[k] = v unless opts.include? k
31
+ end
32
+ tuple = Tuple.new tuple, opts unless tuple.kind_of? Tuple
33
+ calleds = []
34
+ taked = nil
35
+ @callbacks.each do |callback|
36
+ next unless callback[:tuple].match? tuple
37
+ callback[:callback].call tuple
38
+ calleds.push callback
39
+ if callback[:type] == :take
40
+ taked = tuple
41
+ break
42
+ end
43
+ end
44
+ calleds.each do |called|
45
+ @callbacks.delete called
46
+ end
47
+ @tuples.unshift tuple unless taked
48
+ tuple
49
+ end
50
+
51
+ def read(tuple, &block)
52
+ tuple = Tuple.new tuple unless tuple.kind_of? Tuple
53
+ @tuples.each do |t|
54
+ if tuple.match? t
55
+ if block_given?
56
+ block.call t
57
+ return
58
+ else
59
+ return t
60
+ end
61
+ end
62
+ end
63
+ @callbacks.push(:type => :read, :callback => block, :tuple => tuple) if block_given?
64
+ end
65
+
66
+ def take(tuple, &block)
67
+ tuple = Tuple.new tuple unless tuple.kind_of? Tuple
68
+ matched_tuple = nil
69
+ @tuples.each do |t|
70
+ if tuple.match? t
71
+ matched_tuple = t
72
+ break
73
+ end
74
+ end
75
+ if matched_tuple
76
+ @tuples.delete matched_tuple
77
+ if block_given?
78
+ block.call matched_tuple
79
+ else
80
+ return matched_tuple
81
+ end
82
+ else
83
+ @callbacks.push(:type => :take, :callback => block, :tuple => tuple) if block_given?
84
+ end
85
+ end
86
+
87
+ def check_expire
88
+ expires = []
89
+ each do |tuple|
90
+ expires.push tuple unless tuple.expire_at > Time.now
91
+ end
92
+ expires.each do |tuple|
93
+ @tuples.delete tuple
94
+ end
95
+ end
96
+ end
97
+
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,16 @@
1
+ require "sinatra/rocketio/linda/version"
2
+ require "sinatra-rocketio-linda/helper"
3
+ require "sinatra-rocketio-linda/options"
4
+ require "sinatra-rocketio-linda/javascript"
5
+ require "sinatra-rocketio-linda/tuple"
6
+ require "sinatra-rocketio-linda/tuplespace"
7
+ require "sinatra-rocketio-linda/linda"
8
+ require "sinatra-rocketio-linda/application"
9
+
10
+ module Sinatra
11
+ module RocketIO
12
+ module Linda
13
+ end
14
+ end
15
+ register Sinatra::RocketIO::Linda
16
+ end
@@ -0,0 +1,60 @@
1
+ require 'event_emitter'
2
+ require 'sinatra/rocketio/client'
3
+
4
+ module Sinatra
5
+ module RocketIO
6
+ module Linda
7
+
8
+ class Client
9
+ attr_reader :io, :tuplespace
10
+ def initialize(io)
11
+ if io.kind_of? String and io =~ /^https?:\/\/.+$/
12
+ @io = Sinatra::RocketIO::Client.new(io).connect
13
+ elsif io.kind_of? Sinatra::RocketIO::Client
14
+ @io = io
15
+ else
16
+ raise ArgumentError, "argument must be URL or RocketIO::Client"
17
+ end
18
+ @tuplespace = Hash.new{|h,k|
19
+ h[k] = Sinatra::RocketIO::Linda::Client::TupleSpace.new(k, self)
20
+ }
21
+ end
22
+
23
+ class TupleSpace
24
+ attr_reader :name, :linda
25
+ def initialize(name, linda)
26
+ @name = name
27
+ @linda = linda
28
+ end
29
+
30
+ def write(tuple, opts={})
31
+ unless [Hash, Array].include? tuple.class
32
+ raise ArgumentError, "tuple must be Array or Hash"
33
+ end
34
+ @linda.io.push "__linda_write", [@name, tuple, opts]
35
+ end
36
+
37
+ def read(tuple, &block)
38
+ unless [Hash, Array].include? tuple.class
39
+ raise ArgumentError, "tuple must be Array or Hash"
40
+ end
41
+ callback_id = "#{Time.now.to_i}#{Time.now.usec}"
42
+ @linda.io.once "__linda_read_callback_#{callback_id}", &block
43
+ @linda.io.push "__linda_read", [@name, tuple, callback_id]
44
+ end
45
+
46
+ def take(tuple, &block)
47
+ unless [Hash, Array].include? tuple.class
48
+ raise ArgumentError, "tuple must be Array or Hash"
49
+ end
50
+ callback_id = "#{Time.now.to_i}#{Time.now.usec}"
51
+ @linda.io.once "__linda_take_callback_#{callback_id}", &block
52
+ @linda.io.push "__linda_take", [@name, tuple, callback_id]
53
+ end
54
+ end
55
+
56
+ end
57
+
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,7 @@
1
+ module Sinatra
2
+ module RocketIO
3
+ module Linda
4
+ VERSION = "0.0.1"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,29 @@
1
+ $:.unshift File.expand_path '../../lib', File.dirname(__FILE__)
2
+ require 'rubygems'
3
+ require 'bundler/setup'
4
+ require 'sinatra/rocketio/linda/client'
5
+
6
+ linda = Sinatra::RocketIO::Linda::Client.new 'http://localhost:5000'
7
+ ts = linda.tuplespace["calc"]
8
+
9
+ calc = lambda{
10
+ ts.take ["calc_request"] do |tuple|
11
+ query = tuple[1]
12
+ result = eval(query)
13
+ puts "calc: #{query} = #{result}"
14
+ ts.write ["calc_result", result]
15
+ calc.call
16
+ end
17
+ }
18
+
19
+ linda.io.on :connect do
20
+ puts "connect #{io.session}"
21
+ calc.call
22
+ end
23
+
24
+ linda.io.on :disconnect do
25
+ puts "disconnect #{io.session}"
26
+ end
27
+
28
+ loop do
29
+ end
data/sample/config.ru ADDED
@@ -0,0 +1,14 @@
1
+ $:.unshift File.expand_path '../lib', File.dirname(__FILE__)
2
+ require 'rubygems'
3
+ require 'bundler/setup'
4
+ require 'thin'
5
+ require 'sinatra'
6
+ require 'sinatra/rocketio'
7
+ require 'sinatra/reloader' if development?
8
+ require 'sinatra/rocketio/linda'
9
+ require 'haml'
10
+ require File.expand_path 'main', File.dirname(__FILE__)
11
+
12
+ set :linda, :expire_check => 20
13
+
14
+ run Sinatra::Application
data/sample/main.rb ADDED
@@ -0,0 +1,26 @@
1
+ io = Sinatra::RocketIO
2
+ linda = Sinatra::RocketIO::Linda
3
+
4
+ io.on :connect do |client|
5
+ puts "new client connect <#{client}>"
6
+ end
7
+
8
+ io.on :disconnect do |client|
9
+ puts "bye <#{client}>"
10
+ end
11
+
12
+ linda.on :error do |err|
13
+ STDERR.puts err
14
+ end
15
+
16
+ get '/' do
17
+ haml :index
18
+ end
19
+
20
+ get '/worker' do
21
+ haml :worker
22
+ end
23
+
24
+ get '/client' do
25
+ haml :client
26
+ end
@@ -0,0 +1,20 @@
1
+ var io = new RocketIO().connect();
2
+ var linda = new Linda(io);
3
+ var ts = new linda.TupleSpace("calc");
4
+
5
+ $(function(){
6
+ $("#btn_request").click(function(){
7
+ var query = $("#txt_request").val();
8
+ ts.write(["calc_request", query]);
9
+ });
10
+ });
11
+
12
+ var take_result = function(){
13
+ ts.take(["calc_result"], function(tuple){
14
+ var result = tuple[1];
15
+ $("#log").prepend( $("<p>").text(result) );
16
+ take_result();
17
+ });
18
+ };
19
+
20
+ io.on("connect", take_result);
@@ -0,0 +1,14 @@
1
+ var linda = new Linda();
2
+ var ts = new linda.TupleSpace("calc");
3
+
4
+ var calc = function(){
5
+ ts.take(["calc_request"], function(tuple){
6
+ var query = tuple[1];
7
+ var result = eval(query);
8
+ $("#log").prepend( $("<p>").text(query+" = "+result).prepend("calc: ") );
9
+ ts.write(["calc_result", result]);
10
+ calc();
11
+ });
12
+ };
13
+
14
+ linda.io.on("connect", calc);
@@ -0,0 +1,16 @@
1
+ !!!XHTML
2
+ %html
3
+ %head
4
+ %meta{'http-equiv' => 'Content-Type', :content => 'text/html', :charset => 'UTF-8'}
5
+ %title Linda Client on RocketIO
6
+ %script{:src => "//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"}
7
+ %script{:src => rocketio_js}
8
+ %script{:src => linda_js}
9
+ %script{:src => "/client.js"}
10
+ %body
11
+ %h1 Calc Client
12
+ %div#main
13
+ %div#calc
14
+ %input#txt_request{:type => :text, :value => "1+2*3*4-5"}
15
+ %input#btn_request{:type => :button, :value => "request!"}
16
+ %div#log
@@ -0,0 +1,12 @@
1
+ !!!XHTML
2
+ %html
3
+ %head
4
+ %meta{'http-equiv' => 'Content-Type', :content => 'text/html', :charset => 'UTF-8'}
5
+ %title Linda on RocketIO
6
+ %body
7
+ %h1 Linda on RocketIO
8
+ %ul
9
+ %li
10
+ %a{:href => "/worker"} calc worker
11
+ %li
12
+ %a{:href => "/client"} calc client
@@ -0,0 +1,13 @@
1
+ !!!XHTML
2
+ %html
3
+ %head
4
+ %meta{'http-equiv' => 'Content-Type', :content => 'text/html', :charset => 'UTF-8'}
5
+ %title Linda Worker on RocketIO
6
+ %script{:src => "//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"}
7
+ %script{:src => rocketio_js}
8
+ %script{:src => linda_js}
9
+ %script{:src => "/worker.js"}
10
+ %body
11
+ %h1 Calc Worker
12
+ %div#main
13
+ %div#log
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'sinatra/rocketio/linda/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "sinatra-rocketio-linda"
8
+ spec.version = Sinatra::RocketIO::Linda::VERSION
9
+ spec.authors = ["Sho Hashimoto"]
10
+ spec.email = ["hashimoto@shokai.org"]
11
+ spec.description = %q{Linda implementation on Sinatra RocketIO}
12
+ spec.summary = spec.description
13
+ spec.homepage = "https://github.com/shokai/sinatra-rocketio-linda"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/).reject{|i| i == "Gemfile.lock" }
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "minitest"
24
+ spec.add_development_dependency "thin"
25
+ spec.add_development_dependency "haml"
26
+
27
+ spec.add_dependency "sinatra-rocketio"
28
+ spec.add_dependency "event_emitter"
29
+ spec.add_dependency "sinatra"
30
+ end
@@ -0,0 +1,3 @@
1
+ require 'rubygems'
2
+ require 'minitest/autorun'
3
+ $:.unshift File.expand_path '../lib', File.dirname(__FILE__)
@@ -0,0 +1,29 @@
1
+ require File.expand_path 'test_helper', File.dirname(__FILE__)
2
+ require 'sinatra-rocketio-linda/tuple'
3
+
4
+ class TestTuple < MiniTest::Test
5
+ def test_match_array
6
+ tuple = Sinatra::RocketIO::Linda::Tuple.new [1,2,3]
7
+ assert tuple.match? Sinatra::RocketIO::Linda::Tuple.new [1,2,3]
8
+ assert tuple.match? Sinatra::RocketIO::Linda::Tuple.new [1,2,3,4]
9
+ assert !tuple.match?(Sinatra::RocketIO::Linda::Tuple.new [1,2])
10
+ assert !tuple.match?(Sinatra::RocketIO::Linda::Tuple.new [1,"a",3])
11
+ assert !tuple.match?(Sinatra::RocketIO::Linda::Tuple.new :a => 1, :b => 2)
12
+ tuple = Sinatra::RocketIO::Linda::Tuple.new ["a","b","c"]
13
+ assert tuple.match? Sinatra::RocketIO::Linda::Tuple.new ["a","b","c"]
14
+ assert tuple.match? Sinatra::RocketIO::Linda::Tuple.new ["a","b","c","d","efg",123,"h"]
15
+ assert !tuple.match?(Sinatra::RocketIO::Linda::Tuple.new ["a","b"])
16
+ assert !tuple.match?(Sinatra::RocketIO::Linda::Tuple.new ["a","b",789])
17
+ assert !tuple.match?(Sinatra::RocketIO::Linda::Tuple.new :foo => 1, :bar => 2)
18
+ end
19
+
20
+ def test_match_hash
21
+ tuple = Sinatra::RocketIO::Linda::Tuple.new :a => 1, :b => 2
22
+ assert tuple.match? Sinatra::RocketIO::Linda::Tuple.new :a => 1, :b => 2
23
+ assert tuple.match? Sinatra::RocketIO::Linda::Tuple.new :a => 1, :b => 2, :c => 3
24
+ assert tuple.match? Sinatra::RocketIO::Linda::Tuple.new :a => 1, :b => 2, :c => {:foo => "bar"}
25
+ assert !tuple.match?(Sinatra::RocketIO::Linda::Tuple.new :a => 0, :b => 2)
26
+ assert !tuple.match?(Sinatra::RocketIO::Linda::Tuple.new :b => 2, :c => 3)
27
+ assert !tuple.match?(Sinatra::RocketIO::Linda::Tuple.new [1,2,3])
28
+ end
29
+ end
@@ -0,0 +1,110 @@
1
+ require File.expand_path 'test_helper', File.dirname(__FILE__)
2
+ require 'sinatra-rocketio-linda/tuple'
3
+ require 'sinatra-rocketio-linda/tuplespace'
4
+
5
+ class TestTupleSpace < MiniTest::Test
6
+
7
+ def setup
8
+ @space = Sinatra::RocketIO::Linda::TupleSpace.new
9
+ end
10
+
11
+ def test_write_read
12
+ assert_equal @space.size, 0
13
+ @space.write Sinatra::RocketIO::Linda::Tuple.new [1,2,3]
14
+ assert_equal @space.size, 1
15
+ assert_equal @space.read([1,2]).data, [1,2,3]
16
+ @space.write :a => 1, :b => 2, :c => 999
17
+ @space.write :a => 1, :b => 2, :c => 3
18
+ assert_equal @space.size, 3
19
+ assert_equal @space.read(:a => 1, :c => 999).data, {:a => 1, :b => 2, :c => 999}
20
+ assert_equal @space.read(:a => 1, :c => 999).data, {:a => 1, :b => 2, :c => 999}
21
+ assert_equal @space.read(:a => 1).data, {:a => 1, :b => 2, :c => 3}
22
+ end
23
+
24
+ def test_write_read_callback
25
+ assert_equal @space.size, 0
26
+ _tuple1 = nil
27
+ @space.read [1,2] do |tuple|
28
+ _tuple1 = tuple
29
+ end
30
+ _tuple2 = nil
31
+ @space.read [1,"a"] do |tuple|
32
+ _tuple2 = tuple
33
+ end
34
+ _tuple3 = nil
35
+ @space.read [1,2,3] do |tuple|
36
+ _tuple3 = tuple
37
+ end
38
+ @space.write [1,2,3]
39
+ assert_equal _tuple1.data, [1,2,3]
40
+ assert_equal _tuple2, nil
41
+ assert_equal _tuple3.data, [1,2,3]
42
+ assert_equal @space.read([1]).data, [1,2,3]
43
+ assert_equal @space.size, 1
44
+ @space.write [1,2,4]
45
+ assert_equal _tuple1.data, [1,2,3]
46
+ assert_equal @space.size, 2
47
+ end
48
+
49
+ def test_take
50
+ assert_equal @space.size, 0
51
+ 1.upto(3) do |i|
52
+ @space.write [1,2,3,"a"*i]
53
+ end
54
+ assert_equal @space.size, 3
55
+ assert_equal @space.take([1,2,3]).data, [1,2,3,"aaa"]
56
+ assert_equal @space.size, 2
57
+ @space.write :a => 1, :b => 2, :c => 3
58
+ assert_equal @space.size, 3
59
+ assert_equal @space.take([1,3]), nil
60
+ assert_equal @space.take(:a => 1, :b => 2, :c => 4), nil
61
+ assert_equal @space.take([1,2,3]).data, [1,2,3,"aa"]
62
+ assert_equal @space.size, 2
63
+ assert_equal @space.take([1,2,3]).data, [1,2,3,"a"]
64
+ assert_equal @space.size, 1
65
+ assert_equal @space.take(:b => 2, :a => 1).data, {:a => 1, :b => 2, :c => 3}
66
+ assert_equal @space.size, 0
67
+ end
68
+
69
+ def test_take_callback
70
+ assert_equal @space.size, 0
71
+ _tuple1 = nil
72
+ @space.take [1,2] do |tuple|
73
+ _tuple1 = tuple
74
+ end
75
+ _tuple2 = nil
76
+ @space.take [1,"a"] do |tuple|
77
+ _tuple2 = tuple
78
+ end
79
+ _tuple3 = nil
80
+ @space.read [1,2,3] do |tuple|
81
+ _tuple3 = tuple
82
+ end
83
+ _tuple4 = nil
84
+ @space.take [1,2,3] do |tuple|
85
+ _tuple4 = tuple
86
+ end
87
+ 1.upto(3) do |i|
88
+ @space.write [1,2,3,"a"*i]
89
+ end
90
+ assert_equal @space.size, 1
91
+ assert_equal _tuple1.data, [1,2,3,"a"]
92
+ assert_equal _tuple2, nil
93
+ assert_equal _tuple3.data, [1,2,3,"aa"]
94
+ assert_equal _tuple4.data, [1,2,3,"aa"]
95
+ assert_equal @space.take([1]).data, [1,2,3,"aaa"]
96
+ assert_equal @space.size, 0
97
+ end
98
+
99
+ def test_tuple_expire
100
+ @space.write [1,2,3], :expire => 3
101
+ @space.write [1,2,"a","b"], :expire => 2
102
+ assert_equal @space.size, 2
103
+ sleep 2
104
+ @space.check_expire
105
+ assert_equal @space.size, 1
106
+ assert_equal @space.take([1,2]).data, [1,2,3]
107
+ assert_equal @space.size, 0
108
+ end
109
+
110
+ end
metadata ADDED
@@ -0,0 +1,188 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sinatra-rocketio-linda
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Sho Hashimoto
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-05-14 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: thin
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: haml
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: sinatra-rocketio
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: event_emitter
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: sinatra
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - '>='
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ description: Linda implementation on Sinatra RocketIO
126
+ email:
127
+ - hashimoto@shokai.org
128
+ executables: []
129
+ extensions: []
130
+ extra_rdoc_files: []
131
+ files:
132
+ - .gitignore
133
+ - Gemfile
134
+ - History.txt
135
+ - LICENSE.txt
136
+ - README.md
137
+ - Rakefile
138
+ - lib/js/linda.js
139
+ - lib/sinatra-rocketio-linda/application.rb
140
+ - lib/sinatra-rocketio-linda/helper.rb
141
+ - lib/sinatra-rocketio-linda/javascript.rb
142
+ - lib/sinatra-rocketio-linda/linda.rb
143
+ - lib/sinatra-rocketio-linda/options.rb
144
+ - lib/sinatra-rocketio-linda/tuple.rb
145
+ - lib/sinatra-rocketio-linda/tuplespace.rb
146
+ - lib/sinatra/rocketio/linda.rb
147
+ - lib/sinatra/rocketio/linda/client.rb
148
+ - lib/sinatra/rocketio/linda/version.rb
149
+ - sample/bin/cui_calc_worker.rb
150
+ - sample/config.ru
151
+ - sample/main.rb
152
+ - sample/public/client.js
153
+ - sample/public/worker.js
154
+ - sample/views/client.haml
155
+ - sample/views/index.haml
156
+ - sample/views/worker.haml
157
+ - sinatra-rocketio-linda.gemspec
158
+ - test/test_helper.rb
159
+ - test/test_tuple.rb
160
+ - test/test_tuplespace.rb
161
+ homepage: https://github.com/shokai/sinatra-rocketio-linda
162
+ licenses:
163
+ - MIT
164
+ metadata: {}
165
+ post_install_message:
166
+ rdoc_options: []
167
+ require_paths:
168
+ - lib
169
+ required_ruby_version: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - '>='
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ required_rubygems_version: !ruby/object:Gem::Requirement
175
+ requirements:
176
+ - - '>='
177
+ - !ruby/object:Gem::Version
178
+ version: '0'
179
+ requirements: []
180
+ rubyforge_project:
181
+ rubygems_version: 2.0.3
182
+ signing_key:
183
+ specification_version: 4
184
+ summary: Linda implementation on Sinatra RocketIO
185
+ test_files:
186
+ - test/test_helper.rb
187
+ - test/test_tuple.rb
188
+ - test/test_tuplespace.rb