hayeah-ASS 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.
data/ASS.gemspec ADDED
@@ -0,0 +1,48 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{ASS}
5
+ s.version = "0.0.1"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Howard Yeh"]
9
+ s.date = %q{2009-08-13}
10
+ s.email = %q{hayeah@gmail.com}
11
+ s.extra_rdoc_files = [
12
+ "LICENSE",
13
+ "README.textile"
14
+ ]
15
+ s.files = [
16
+ "ASS.gemspec",
17
+ "LICENSE",
18
+ "README.textile",
19
+ "Rakefile",
20
+ "VERSION.yml",
21
+ "lib/ass.rb",
22
+ "test/ass_test.rb",
23
+ "test/test_helper.rb"
24
+ ]
25
+ s.has_rdoc = true
26
+ s.homepage = %q{http://github.com/hayeah/ass}
27
+ s.rdoc_options = ["--charset=UTF-8"]
28
+ s.require_paths = ["lib"]
29
+ s.rubygems_version = %q{1.3.1}
30
+ s.summary = %q{Asynchronous Service Stages for Distributed Services}
31
+ s.test_files = [
32
+ "test/ass_test.rb",
33
+ "test/test_helper.rb"
34
+ ]
35
+
36
+ if s.respond_to? :specification_version then
37
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
38
+ s.specification_version = 2
39
+
40
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
41
+ s.add_runtime_dependency(%q<amqp>, [">= 0"])
42
+ else
43
+ s.add_dependency(%q<amqp>, [">= 0"])
44
+ end
45
+ else
46
+ s.add_dependency(%q<amqp>, [">= 0"])
47
+ end
48
+ end
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Howard Yeh
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.textile ADDED
File without changes
data/Rakefile ADDED
@@ -0,0 +1,57 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "ASS"
8
+ gem.summary = "Asynchronous Service Stages for Distributed Services"
9
+ gem.email = "hayeah@gmail.com"
10
+ gem.homepage = "http://github.com/hayeah/ass"
11
+ gem.authors = ["Howard Yeh"]
12
+ gem.add_dependency "amqp"
13
+ gem.files = FileList["[A-Z]*", "{lib,test}/**/*"]
14
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
15
+ end
16
+ rescue LoadError
17
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
18
+ end
19
+
20
+ require 'rake/testtask'
21
+ Rake::TestTask.new(:test) do |test|
22
+ test.libs << 'lib' << 'test'
23
+ test.pattern = 'test/**/*_test.rb'
24
+ test.verbose = true
25
+ end
26
+
27
+ begin
28
+ require 'rcov/rcovtask'
29
+ Rcov::RcovTask.new do |test|
30
+ test.libs << 'test'
31
+ test.pattern = 'test/**/*_test.rb'
32
+ test.verbose = true
33
+ end
34
+ rescue LoadError
35
+ task :rcov do
36
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
37
+ end
38
+ end
39
+
40
+
41
+ task :default => :test
42
+
43
+ require 'rake/rdoctask'
44
+ Rake::RDocTask.new do |rdoc|
45
+ if File.exist?('VERSION.yml')
46
+ config = YAML.load(File.read('VERSION.yml'))
47
+ version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
48
+ else
49
+ version = ""
50
+ end
51
+
52
+ rdoc.rdoc_dir = 'rdoc'
53
+ rdoc.title = "ass #{version}"
54
+ rdoc.rdoc_files.include('README*')
55
+ rdoc.rdoc_files.include('lib/**/*.rb')
56
+ end
57
+
data/VERSION.yml ADDED
@@ -0,0 +1,4 @@
1
+ ---
2
+ :major: 0
3
+ :minor: 0
4
+ :patch: 1
data/lib/ass.rb ADDED
@@ -0,0 +1,212 @@
1
+ require 'mq'
2
+ class Ass
3
+
4
+ attr_reader :server_exchange
5
+
6
+ def self.declare(server_exchange)
7
+ self.new([server_exchange,{:passive => true}])
8
+ end
9
+
10
+ # uh... we'll assume that the exchanges are all direct exchanges.
11
+ def initialize(server_exchange)
12
+ @server_exchange = get_exchange(server_exchange)
13
+ end
14
+
15
+ def client(client_exchange,*args)
16
+ @client_exchange ||= get_exchange(client_exchange)
17
+ q = get_queue(@client_exchange,*args)
18
+ Client.new(@server_exchange,@client_exchange,q)
19
+ end
20
+
21
+ def server(*args)
22
+ Server.new(@server_exchange,get_queue(@server_exchange,*args))
23
+ end
24
+
25
+ def get_exchange(arg)
26
+ case arg
27
+ when Array
28
+ exchanges = exchange[0]
29
+ opts = exchange[1]
30
+ else
31
+ exchange = arg
32
+ opts = nil
33
+ end
34
+ opts = {} if opts.nil?
35
+ exchange = exchange.is_a?(MQ::Exchange) ? exchange : MQ.direct(exchange,opts)
36
+ raise "accepts only direct exchanges" unless exchange.type == :direct
37
+ exchange
38
+ end
39
+
40
+ # can specify a key to create a queue for that subdomain
41
+ def get_queue(exchange,*args)
42
+ case args[0]
43
+ when Hash
44
+ key = nil
45
+ opts = args[0]
46
+ when String
47
+ key = args[0]
48
+ opts = args[1]
49
+ end
50
+ opts = {} if opts.nil?
51
+ if key
52
+ name = "#{exchange.name}--#{key}"
53
+ q = MQ.queue(name,opts)
54
+ q.bind(exchange,{ :routing_key => key})
55
+ else
56
+ q = MQ.queue(exchange.name,opts)
57
+ q.bind(exchange,{ :routing_key => exchange.name })
58
+ end
59
+ q
60
+ end
61
+
62
+ module Callback
63
+
64
+ def build_callback_klass(callback)
65
+ case callback
66
+ when Proc
67
+ Class.new &callback
68
+ when Class
69
+ callback
70
+ when Module
71
+ Class.new { include callback }
72
+ end
73
+ end
74
+
75
+ def callback(info,payload)
76
+ # method,data,meta
77
+ if @callback_klass.respond_to? :version
78
+ klass = @callback_klass.get_version(payload[:version])
79
+ else
80
+ klass = @callback_klass
81
+ end
82
+ obj = klass.new
83
+ service = self
84
+ obj.instance_variable_set("@__service__",service)
85
+ obj.instance_variable_set("@__header__",info)
86
+ obj.instance_variable_set("@__meta__",payload[:meta])
87
+ class << obj
88
+ def header
89
+ @__header__
90
+ end
91
+
92
+ def meta
93
+ @__meta__
94
+ end
95
+
96
+ def service
97
+ @__service__
98
+ end
99
+
100
+ def call(method,data=nil,meta=nil,opts={})
101
+ @__service__.call(method,data,meta,opts)
102
+ end
103
+ end
104
+ #p [:call,payload]
105
+ obj.send(payload[:method],
106
+ payload[:data])
107
+ end
108
+ end
109
+
110
+ class Client
111
+ include Callback
112
+ def initialize(server_exchange,client_exchange,queue)
113
+ @server_exchange = server_exchange
114
+ @client_exchange = client_exchange
115
+ @queue = queue
116
+ end
117
+
118
+ def react(callback=nil,opts=nil,&block)
119
+ if block
120
+ opts = callback
121
+ callback = block
122
+ end
123
+ opts = {} if opts.nil?
124
+
125
+ @callback_klass = build_callback_klass(callback)
126
+ @ack = opts[:ack]
127
+ @queue.subscribe(opts) do |info,payload|
128
+ payload = ::Marshal.load(payload)
129
+ callback(info,payload)
130
+ info.ack if @ack
131
+ end
132
+ self
133
+ end
134
+
135
+ def call(method,data=nil,meta=nil,opts={})
136
+ # opts passed to publish
137
+ # if no routing key is given, use receiver's name as the routing key.
138
+ version = @klass.version if @klass.respond_to? :version
139
+ payload = {
140
+ :method => method,
141
+ :data => data,
142
+ :meta => meta,
143
+ :version => version
144
+ }
145
+
146
+ # set it up s.t. server would respond to
147
+ # private queue if key is given, otherwise
148
+ # the server would respond to public queue.
149
+ key = opts.delete(:key)
150
+ @server_exchange.publish Marshal.dump(payload), {
151
+ :key => (key ? key : @server_exchange.name),
152
+ :reply_to => @client_exchange.name
153
+ }.merge(opts)
154
+ end
155
+
156
+ # for casting, just null the reply_to field, so server doesn't respond.
157
+ def cast(method,data=nil,meta=nil,opts={})
158
+ self.call(method,data,meta,opts.merge({:reply_to => nil}))
159
+ end
160
+
161
+
162
+ end
163
+
164
+ class Server
165
+ include Callback
166
+
167
+ def initialize(server_exchange,q)
168
+ @queue = q
169
+ @server_exchange = server_exchange
170
+ end
171
+
172
+ attr_reader :queue
173
+ def exchange
174
+ @server_exchange
175
+ end
176
+
177
+ def react(callback=nil,opts=nil,&block)
178
+ if block
179
+ opts = callback
180
+ callback = block
181
+ end
182
+ opts = {} if opts.nil?
183
+
184
+ @callback_klass = build_callback_klass(callback)
185
+ @ack = opts[:ack]
186
+ @queue.subscribe(opts) do |info,payload|
187
+ payload = ::Marshal.load(payload)
188
+ #p [info,info.reply_to,payload]
189
+ data2 = callback(info,payload)
190
+ payload2 = payload.merge :data => data2
191
+ if info.routing_key == @server_exchange.name
192
+ # addressed to the server's public
193
+ # queue, respond to the routing_key of
194
+ # the client's public queue.
195
+ key = info.reply_to
196
+ else
197
+ # addressed to the private queue
198
+ key = info.routing_key
199
+ end
200
+ MQ.direct(info.reply_to).publish(::Marshal.dump(payload2),:routing_key => key) if info.reply_to
201
+ info.ack if @ack
202
+ end
203
+ self
204
+ end
205
+ end
206
+
207
+ class Peeper
208
+ def initialize(exchange,callback)
209
+ # create a temporary queue that binds to an exchange
210
+ end
211
+ end
212
+ end
data/test/ass_test.rb ADDED
@@ -0,0 +1,7 @@
1
+ require 'test_helper'
2
+
3
+ class AssTest < Test::Unit::TestCase
4
+ should "probably rename this file and start testing for real" do
5
+ flunk "hey buddy, you should probably rename this file and start testing for real"
6
+ end
7
+ end
@@ -0,0 +1,10 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+
5
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
6
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
7
+ require 'ass'
8
+
9
+ class Test::Unit::TestCase
10
+ end
metadata ADDED
@@ -0,0 +1,72 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: hayeah-ASS
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Howard Yeh
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-08-13 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: amqp
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ description:
26
+ email: hayeah@gmail.com
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - LICENSE
33
+ - README.textile
34
+ files:
35
+ - ASS.gemspec
36
+ - LICENSE
37
+ - README.textile
38
+ - Rakefile
39
+ - VERSION.yml
40
+ - lib/ass.rb
41
+ - test/ass_test.rb
42
+ - test/test_helper.rb
43
+ has_rdoc: true
44
+ homepage: http://github.com/hayeah/ass
45
+ licenses:
46
+ post_install_message:
47
+ rdoc_options:
48
+ - --charset=UTF-8
49
+ require_paths:
50
+ - lib
51
+ required_ruby_version: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: "0"
56
+ version:
57
+ required_rubygems_version: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: "0"
62
+ version:
63
+ requirements: []
64
+
65
+ rubyforge_project:
66
+ rubygems_version: 1.3.5
67
+ signing_key:
68
+ specification_version: 2
69
+ summary: Asynchronous Service Stages for Distributed Services
70
+ test_files:
71
+ - test/ass_test.rb
72
+ - test/test_helper.rb