cloudist 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,36 @@
1
+ module Cloudist
2
+ module Utils
3
+ extend self
4
+
5
+ def reply_prefix(name)
6
+ "temp.reply.#{name}"
7
+ end
8
+
9
+ def generate_queue(exchange_name, second_name=nil)
10
+ second_name ||= $$
11
+ "#{generate_name_for_instance(exchange_name)}.#{second_name}"
12
+ end
13
+
14
+ def generate_name_for_instance(name)
15
+ "#{name}.#{Socket.gethostname}"
16
+ end
17
+
18
+ # DEPRECATED
19
+ def generate_reply_to(name)
20
+ "#{reply_prefix(name)}.#{generate_sym}"
21
+ end
22
+
23
+ def generate_sym
24
+ values = [
25
+ rand(0x0010000),
26
+ rand(0x0010000),
27
+ rand(0x0010000),
28
+ rand(0x0010000),
29
+ rand(0x0010000),
30
+ rand(0x1000000),
31
+ rand(0x1000000),
32
+ ]
33
+ "%04x%04x%04x%04x%04x%06x%06x" % values
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,24 @@
1
+ module Cloudist
2
+ class Worker
3
+
4
+ attr_reader :options
5
+
6
+ def initialize(options)
7
+ @options = options
8
+ end
9
+
10
+ def log
11
+ Cloudist.log
12
+ end
13
+
14
+ def job(queue_name, &block)
15
+ q = JobQueue.new(queue_name)
16
+ q.subscribe do |request|
17
+ j = Job.new(request.payload.dup)
18
+ j.instance_eval(&block)
19
+ j.cleanup
20
+ end
21
+ end
22
+
23
+ end
24
+ end
@@ -0,0 +1,33 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '../../spec_helper')
2
+
3
+ describe "Cloudist" do
4
+ describe "BasicQueue" do
5
+ before(:each) do
6
+ overload_amqp
7
+ reset_broker
8
+ end
9
+
10
+ it "should create a queue and exchange" do
11
+ # MQ.stubs(:direct).with(:name).returns(true)
12
+ @mq = mock("MQ")
13
+ @exchange = mock("MQ Exchange")
14
+ @queue = mock("MQ Queue")
15
+
16
+ @queue.expects(:bind).with(@exchange)
17
+ # @mq.expects(:queue).with("make.sandwich")
18
+
19
+ bq = Cloudist::BasicQueue.new("make.sandwich")
20
+ bq.stubs(:q).returns(@queue)
21
+ bq.stubs(:mq).returns(@mq)
22
+ bq.stubs(:ex).returns(@exchange)
23
+
24
+ bq.setup
25
+
26
+ bq.q.should_not be_nil
27
+ bq.ex.should_not be_nil
28
+ bq.mq.should_not be_nil
29
+ end
30
+
31
+ end
32
+
33
+ end
@@ -0,0 +1,23 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '../../spec_helper')
2
+
3
+ describe Cloudist::Job do
4
+ before(:each) do
5
+ @payload = Cloudist::Payload.new({:bread => 'white'})
6
+ end
7
+
8
+ it "should be constructable with payload" do
9
+ job = Cloudist::Job.new(@payload)
10
+ job.payload.should == @payload
11
+ end
12
+
13
+ it "should be constructable with payload and return ID" do
14
+ job = Cloudist::Job.new(@payload)
15
+ job.id.should == @payload.id
16
+ end
17
+
18
+ it "should be constructable with payload and return data" do
19
+ job = Cloudist::Job.new(@payload)
20
+ job.data.should == @payload.body
21
+ end
22
+
23
+ end
@@ -0,0 +1,126 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '../../spec_helper')
2
+
3
+ describe Cloudist::Payload do
4
+ it "should raise bad payload error unless data is a hash" do
5
+ lambda {
6
+ Cloudist::Payload.new([1,2,3])
7
+ }.should raise_error(Cloudist::BadPayload)
8
+ end
9
+
10
+ it "should accept a hash for data" do
11
+ lambda {
12
+ Cloudist::Payload.new({:bread => 'white'})
13
+ }.should_not raise_error(Cloudist::BadPayload)
14
+ end
15
+
16
+ it "should prepare headers" do
17
+ payload = Cloudist::Payload.new({:bread => 'white'})
18
+ body, headers = payload.apply_custom_headers
19
+ body.should == {"bread"=>"white"}
20
+ headers.has_key?(:ttl).should be_true
21
+ headers.has_key?(:content_type).should be_true
22
+ headers[:content_type].should == "application/json"
23
+ headers.has_key?(:published_on).should be_true
24
+ headers.has_key?(:event_hash).should be_true
25
+ headers.has_key?(:message_id).should be_true
26
+ end
27
+
28
+ it "should extract published_on from data" do
29
+ payload = Cloudist::Payload.new({:bread => 'white', :published_on => 12345678})
30
+ body, headers = payload.apply_custom_headers
31
+ body.should == {"bread"=>"white"}
32
+ headers[:published_on].should == "12345678"
33
+ end
34
+
35
+ it "should extract custom event hash from data" do
36
+ payload = Cloudist::Payload.new({:bread => 'white', :event_hash => 'foo'})
37
+ body, headers = payload.apply_custom_headers
38
+ body.should == {"bread"=>"white"}
39
+ headers[:event_hash].should == "foo"
40
+ end
41
+
42
+ it "should parse JSON message" do
43
+ payload = Cloudist::Payload.new({:bread => 'white', :event_hash => 'foo'}.to_json)
44
+ payload.body.should == {"bread"=>"white"}
45
+ end
46
+
47
+ it "should parse custom headers" do
48
+ payload = Cloudist::Payload.new({:bread => 'white', :event_hash => 'foo'}.to_json, {:published_on => 12345})
49
+ payload.parse_custom_headers.should == {:published_on=>12345, :event_hash=>"foo", :content_type=>"application/json", :message_id=>"foo", :ttl=>300}
50
+ end
51
+
52
+ it "should create a unique event hash" do
53
+ payload = Cloudist::Payload.new({:bread => 'white'})
54
+ payload.create_event_hash.size.should == 32
55
+ end
56
+
57
+ it "should not create a new event hash unless it doesn't have one" do
58
+ payload = Cloudist::Payload.new({:bread => 'white'})
59
+ payload.event_hash.size.should == 32
60
+ payload = Cloudist::Payload.new({:bread => 'white'}, {:event_hash => 'foo'})
61
+ payload.event_hash.should == 'foo'
62
+ end
63
+
64
+ it "should delegate missing methods to header keys" do
65
+ payload = Cloudist::Payload.new({:bread => 'white'}, {:event_hash => 'foo', :ttl => 300})
66
+ payload[:bread].should == 'white'
67
+ end
68
+
69
+ it "should format payload for sending" do
70
+ payload = Cloudist::Payload.new({:bread => 'white'}, {:event_hash => 'foo'})
71
+ json, headers = payload.formatted
72
+ json.should == "{\"bread\":\"white\"}"
73
+ headers[:ttl].should == "300"
74
+ end
75
+
76
+ it "should generate a unique payload ID" do
77
+ payload = Cloudist::Payload.new({:bread => 'white'})
78
+ payload.id.size.should == 32
79
+ end
80
+
81
+ it "should allow setting of payload ID" do
82
+ payload = Cloudist::Payload.new({:bread => 'white'})
83
+ payload.id = "2345"
84
+ payload.id.should == "2345"
85
+ end
86
+
87
+ it "should allow changing of payload after being published" do
88
+ payload = Cloudist::Payload.new({:bread => 'white'})
89
+ payload.publish
90
+ lambda { payload.id = "12334456" }.should raise_error
91
+ end
92
+
93
+ it "should freeze" do
94
+ payload = Cloudist::Payload.new({:bread => 'white'})
95
+ lambda {payload.body[:bread] = "brown"}.should_not raise_error(TypeError)
96
+ payload.body[:bread].should == "brown"
97
+ payload.publish
98
+ lambda {payload.body[:bread] = "rainbow"}.should raise_error(TypeError)
99
+ end
100
+
101
+ it "should allow setting of reply header" do
102
+ payload = Cloudist::Payload.new({:bread => 'white'})
103
+
104
+ payload.headers[:reply_to].should be_nil
105
+ payload.set_reply_to("my_custom_queue")
106
+ payload.headers[:reply_to].should_not be_nil
107
+ payload.headers[:reply_to].should match /^temp\.reply\.my_custom_queue\.(.+)/
108
+ body, headers = payload.formatted
109
+ headers[:reply_to].should == payload.headers[:reply_to]
110
+
111
+ end
112
+
113
+ it "should not overwrite passed in headers" do
114
+ payload = Cloudist::Payload.new({:bread => 'white'}, {:ttl => 25, :event_hash => 'foo', :published_on => 12345, :message_id => 1})
115
+ payload.headers[:ttl].should == "25"
116
+ payload.headers[:event_hash].should == "foo"
117
+ payload.headers[:published_on].should == "12345"
118
+ payload.headers[:message_id].should == "1"
119
+ end
120
+
121
+ it "should allow custom headers to be set" do
122
+ payload = Cloudist::Payload.new({:bread => 'white'}, {:reply_type => 'event'})
123
+ payload.headers[:reply_type].should == 'event'
124
+ end
125
+
126
+ end
@@ -0,0 +1,41 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '../../spec_helper')
2
+
3
+ describe Cloudist::Request do
4
+ before {
5
+ @mq_header = mock("MQ::Header")
6
+ @mq_header.stubs(:properties).returns({:published_on=>Time.now.to_i - 60, :event_hash=>"foo", :content_type=>"application/json", :message_id=>"foo", :ttl=>300})
7
+
8
+ q = Cloudist::JobQueue.new('test.queue')
9
+
10
+ @request = Cloudist::Request.new(q, {:bread => 'white'}.to_json, @mq_header)
11
+ }
12
+
13
+ it "should return ttl" do
14
+ @request.ttl.should == 300
15
+ end
16
+
17
+ it "should have a payload" do
18
+ @request.payload.should_not be_nil
19
+ @request.payload.should be_a(Cloudist::Payload)
20
+ end
21
+
22
+ it "should be 1 minute old" do
23
+ @request.age.should == 60
24
+ end
25
+
26
+ it "should not be expired" do
27
+ @request.expired?.should_not be_true
28
+ end
29
+
30
+ it "should not be acked yet" do
31
+ @request.acked?.should be_false
32
+ end
33
+
34
+ it "should be ackable" do
35
+ @mq_header.stubs(:ack).returns(true)
36
+
37
+ @request.ack.should be_true
38
+ @request.acked?.should be_true
39
+ end
40
+
41
+ end
@@ -0,0 +1,24 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "Cloudist" do
4
+
5
+ before(:each) do
6
+ overload_amqp
7
+ reset_broker
8
+ end
9
+
10
+ def run_start
11
+ Cloudist.start {
12
+ worker {
13
+
14
+ }
15
+ }
16
+ end
17
+
18
+ it "should start" do
19
+ Cloudist.stubs(:worker).returns(true)
20
+ Cloudist.expects(:worker).once
21
+
22
+ # run_start
23
+ end
24
+ end
@@ -0,0 +1,16 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '../../spec_helper')
2
+
3
+ require "cloudist/core_ext/string"
4
+
5
+ describe "String" do
6
+ it "should support ends_with?" do
7
+ "started!".ends_with?('!').should be_true
8
+ "started!".ends_with?('-').should be_false
9
+ end
10
+
11
+ it "should support starts_with?" do
12
+ "event-started".starts_with?("event").should be_true
13
+ "event-started".starts_with?("reply").should be_false
14
+ end
15
+
16
+ end
@@ -0,0 +1,15 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+ require 'rspec'
4
+ require "moqueue"
5
+ require "mocha"
6
+
7
+ require 'cloudist'
8
+
9
+ # Requires supporting files with custom matchers and macros, etc,
10
+ # in ./support/ and its subdirectories.
11
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
12
+
13
+ RSpec.configure do |config|
14
+ config.mock_with :mocha
15
+ end
metadata ADDED
@@ -0,0 +1,270 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cloudist
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 2
10
+ version: 0.0.2
11
+ platform: ruby
12
+ authors:
13
+ - Ivan Vanderbyl
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-01-16 00:00:00 +11:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ type: :runtime
23
+ prerelease: false
24
+ name: amqp
25
+ version_requirements: &id001 !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ">="
29
+ - !ruby/object:Gem::Version
30
+ hash: 3
31
+ segments:
32
+ - 0
33
+ version: "0"
34
+ requirement: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ type: :runtime
37
+ prerelease: false
38
+ name: json
39
+ version_requirements: &id002 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ hash: 3
45
+ segments:
46
+ - 0
47
+ version: "0"
48
+ requirement: *id002
49
+ - !ruby/object:Gem::Dependency
50
+ type: :runtime
51
+ prerelease: false
52
+ name: activesupport
53
+ version_requirements: &id003 !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ hash: 3
59
+ segments:
60
+ - 0
61
+ version: "0"
62
+ requirement: *id003
63
+ - !ruby/object:Gem::Dependency
64
+ type: :development
65
+ prerelease: false
66
+ name: rspec
67
+ version_requirements: &id004 !ruby/object:Gem::Requirement
68
+ none: false
69
+ requirements:
70
+ - - ~>
71
+ - !ruby/object:Gem::Version
72
+ hash: 3
73
+ segments:
74
+ - 2
75
+ - 3
76
+ - 0
77
+ version: 2.3.0
78
+ requirement: *id004
79
+ - !ruby/object:Gem::Dependency
80
+ type: :development
81
+ prerelease: false
82
+ name: moqueue
83
+ version_requirements: &id005 !ruby/object:Gem::Requirement
84
+ none: false
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ hash: 3
89
+ segments:
90
+ - 0
91
+ version: "0"
92
+ requirement: *id005
93
+ - !ruby/object:Gem::Dependency
94
+ type: :development
95
+ prerelease: false
96
+ name: mocha
97
+ version_requirements: &id006 !ruby/object:Gem::Requirement
98
+ none: false
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ hash: 3
103
+ segments:
104
+ - 0
105
+ version: "0"
106
+ requirement: *id006
107
+ - !ruby/object:Gem::Dependency
108
+ type: :development
109
+ prerelease: false
110
+ name: bundler
111
+ version_requirements: &id007 !ruby/object:Gem::Requirement
112
+ none: false
113
+ requirements:
114
+ - - ~>
115
+ - !ruby/object:Gem::Version
116
+ hash: 23
117
+ segments:
118
+ - 1
119
+ - 0
120
+ - 0
121
+ version: 1.0.0
122
+ requirement: *id007
123
+ - !ruby/object:Gem::Dependency
124
+ type: :development
125
+ prerelease: false
126
+ name: jeweler
127
+ version_requirements: &id008 !ruby/object:Gem::Requirement
128
+ none: false
129
+ requirements:
130
+ - - ~>
131
+ - !ruby/object:Gem::Version
132
+ hash: 7
133
+ segments:
134
+ - 1
135
+ - 5
136
+ - 2
137
+ version: 1.5.2
138
+ requirement: *id008
139
+ - !ruby/object:Gem::Dependency
140
+ type: :development
141
+ prerelease: false
142
+ name: rcov
143
+ version_requirements: &id009 !ruby/object:Gem::Requirement
144
+ none: false
145
+ requirements:
146
+ - - ">="
147
+ - !ruby/object:Gem::Version
148
+ hash: 3
149
+ segments:
150
+ - 0
151
+ version: "0"
152
+ requirement: *id009
153
+ - !ruby/object:Gem::Dependency
154
+ type: :development
155
+ prerelease: false
156
+ name: reek
157
+ version_requirements: &id010 !ruby/object:Gem::Requirement
158
+ none: false
159
+ requirements:
160
+ - - ~>
161
+ - !ruby/object:Gem::Version
162
+ hash: 15
163
+ segments:
164
+ - 1
165
+ - 2
166
+ - 8
167
+ version: 1.2.8
168
+ requirement: *id010
169
+ - !ruby/object:Gem::Dependency
170
+ type: :development
171
+ prerelease: false
172
+ name: roodi
173
+ version_requirements: &id011 !ruby/object:Gem::Requirement
174
+ none: false
175
+ requirements:
176
+ - - ~>
177
+ - !ruby/object:Gem::Version
178
+ hash: 11
179
+ segments:
180
+ - 2
181
+ - 1
182
+ - 0
183
+ version: 2.1.0
184
+ requirement: *id011
185
+ description: Cloudist is a simple, highly scalable job queue for Ruby applications, it can run within Rails, or on EC2, and does not load your entire Rails stack like delayed job does.
186
+ email: ivanvanderbyl@me.com
187
+ executables: []
188
+
189
+ extensions: []
190
+
191
+ extra_rdoc_files:
192
+ - LICENSE.txt
193
+ - README.md
194
+ files:
195
+ - .document
196
+ - .rspec
197
+ - Gemfile
198
+ - Gemfile.lock
199
+ - LICENSE.txt
200
+ - README.md
201
+ - Rakefile
202
+ - VERSION
203
+ - examples/queue_message.rb
204
+ - examples/sandwich_client.rb
205
+ - examples/sandwich_worker.rb
206
+ - lib/cloudist.rb
207
+ - lib/cloudist/basic_queue.rb
208
+ - lib/cloudist/core_ext/string.rb
209
+ - lib/cloudist/errors.rb
210
+ - lib/cloudist/job.rb
211
+ - lib/cloudist/job_queue.rb
212
+ - lib/cloudist/listener.rb
213
+ - lib/cloudist/payload.rb
214
+ - lib/cloudist/publisher.rb
215
+ - lib/cloudist/reply_queue.rb
216
+ - lib/cloudist/request.rb
217
+ - lib/cloudist/utils.rb
218
+ - lib/cloudist/worker.rb
219
+ - spec/cloudist/basic_queue_spec.rb
220
+ - spec/cloudist/job_spec.rb
221
+ - spec/cloudist/payload_spec.rb
222
+ - spec/cloudist/request_spec.rb
223
+ - spec/cloudist_spec.rb
224
+ - spec/core_ext/string_spec.rb
225
+ - spec/spec_helper.rb
226
+ has_rdoc: true
227
+ homepage: http://github.com/ivanvanderbyl/cloudist
228
+ licenses:
229
+ - MIT
230
+ post_install_message:
231
+ rdoc_options: []
232
+
233
+ require_paths:
234
+ - lib
235
+ required_ruby_version: !ruby/object:Gem::Requirement
236
+ none: false
237
+ requirements:
238
+ - - ">="
239
+ - !ruby/object:Gem::Version
240
+ hash: 3
241
+ segments:
242
+ - 0
243
+ version: "0"
244
+ required_rubygems_version: !ruby/object:Gem::Requirement
245
+ none: false
246
+ requirements:
247
+ - - ">="
248
+ - !ruby/object:Gem::Version
249
+ hash: 3
250
+ segments:
251
+ - 0
252
+ version: "0"
253
+ requirements: []
254
+
255
+ rubyforge_project:
256
+ rubygems_version: 1.3.7
257
+ signing_key:
258
+ specification_version: 3
259
+ summary: Super fast job queue using AMQP
260
+ test_files:
261
+ - examples/queue_message.rb
262
+ - examples/sandwich_client.rb
263
+ - examples/sandwich_worker.rb
264
+ - spec/cloudist/basic_queue_spec.rb
265
+ - spec/cloudist/job_spec.rb
266
+ - spec/cloudist/payload_spec.rb
267
+ - spec/cloudist/request_spec.rb
268
+ - spec/cloudist_spec.rb
269
+ - spec/core_ext/string_spec.rb
270
+ - spec/spec_helper.rb