cloudist 0.0.2

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.
@@ -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