right_agent 0.13.5 → 0.14.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (c) 2009-2011 RightScale Inc
2
+ # Copyright (c) 2009-2012 RightScale Inc
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining
5
5
  # a copy of this software and associated documentation files (the
@@ -75,311 +75,249 @@ class Doomed
75
75
  on_exception :doh
76
76
  end
77
77
 
78
- # Mock the EventMachine deferrer.
79
- class EMMock
80
- def self.defer(op = nil, callback = nil)
81
- callback.call(op.call)
82
- end
83
- end
84
-
85
- # Mock the EventMachine deferrer but do not do callback.
86
- class EMMockNoCallback
87
- def self.defer(op = nil, callback = nil)
88
- op.call
89
- end
90
- end
91
-
92
78
  describe "RightScale::Dispatcher" do
93
79
 
94
80
  include FlexMock::ArgumentTypes
95
81
 
96
82
  before(:each) do
97
- flexmock(RightScale::Log).should_receive(:error).by_default.and_return { |m| raise RightScale::Log.format(*m) }
98
- flexmock(RightScale::Log).should_receive(:info).by_default
83
+ @log = flexmock(RightScale::Log)
84
+ @log.should_receive(:error).by_default.and_return { |m| raise RightScale::Log.format(*m) }
85
+ @log.should_receive(:info).by_default
99
86
  @now = Time.at(1000000)
100
87
  flexmock(Time).should_receive(:now).and_return(@now).by_default
101
- @broker = flexmock("Broker", :subscribe => true, :publish => true).by_default
102
88
  @actor = Foo.new
103
89
  @registry = RightScale::ActorRegistry.new
104
90
  @registry.register(@actor, nil)
105
91
  @agent_id = "rs-agent-1-1"
106
- @agent = flexmock("Agent", :identity => @agent_id, :broker => @broker, :registry => @registry, :options => {}).by_default
92
+ @agent = flexmock("Agent", :identity => @agent_id, :registry => @registry).by_default
107
93
  @cache = RightScale::DispatchedCache.new(@agent_id)
108
94
  @dispatcher = RightScale::Dispatcher.new(@agent, @cache)
109
- @dispatcher.em = EMMock
110
- @response_queue = RightScale::Dispatcher::RESPONSE_QUEUE
111
- @header = flexmock("amqp header")
112
- @header.should_receive(:ack).once.by_default
113
95
  end
114
96
 
115
- it "should dispatch a request" do
116
- req = RightScale::Request.new('/foo/bar', 'you', :token => 'token')
117
- res = @dispatcher.dispatch(req, @header)
118
- res.should(be_kind_of(RightScale::Result))
119
- res.token.should == 'token'
120
- res.results.should == ['hello', 'you']
121
- end
97
+ context "routable?" do
122
98
 
123
- it "should dispatch a request with required arity" do
124
- req = RightScale::Request.new('/foo/bar2', 'you', :token => 'token')
125
- res = @dispatcher.dispatch(req, @header)
126
- res.should(be_kind_of(RightScale::Result))
127
- res.token.should == 'token'
128
- res.results.should == ['hello', 'you', req]
129
- end
99
+ it "should return false if actor is not available for routing" do
100
+ @dispatcher.routable?("foo").should be_true
101
+ end
130
102
 
131
- it "should dispatch a request to the default action" do
132
- req = RightScale::Request.new('/foo', 'you', :token => 'token')
133
- res = @dispatcher.dispatch(req, @header)
134
- res.should(be_kind_of(RightScale::Result))
135
- res.token.should == req.token
136
- res.results.should == ['hello', 'you']
137
- end
103
+ it "should return true if actor is available for routing" do
104
+ @dispatcher.routable?("bar").should be_false
105
+ end
138
106
 
139
- it "should publish result of request to response queue" do
140
- req = RightScale::Request.new('/foo', 'you', :token => 'token')
141
- req.reply_to = "rs-mapper-1-1"
142
- @broker.should_receive(:publish).with(hsh(:name => @response_queue),
143
- on {|arg| arg.class == RightScale::Result &&
144
- arg.to == "rs-mapper-1-1" &&
145
- arg.results == ['hello', 'you']},
146
- hsh(:persistent => true, :mandatory => true)).once
147
- @dispatcher.dispatch(req, @header)
148
107
  end
149
108
 
150
- it "should handle custom prefixes" do
151
- @registry.register(Foo.new, 'umbongo')
152
- req = RightScale::Request.new('/umbongo/bar', 'you')
153
- res = @dispatcher.dispatch(req, @header)
154
- res.should(be_kind_of(RightScale::Result))
155
- res.token.should == req.token
156
- res.results.should == ['hello', 'you']
157
- end
109
+ context "dispatch" do
158
110
 
159
- it "should call the on_exception callback if something goes wrong" do
160
- flexmock(RightScale::Log).should_receive(:error).once
161
- req = RightScale::Request.new('/foo/i_kill_you', nil)
162
- flexmock(@actor).should_receive(:handle_exception).with(:i_kill_you, req, Exception).once
163
- res = @dispatcher.dispatch(req, @header)
164
- res.results.error?.should be_true
165
- (res.results.content =~ /Could not handle \/foo\/i_kill_you request/).should be_true
166
- end
111
+ it "should dispatch a request" do
112
+ req = RightScale::Request.new('/foo/bar', 'you', :token => 'token')
113
+ res = @dispatcher.dispatch(req)
114
+ res.should(be_kind_of(RightScale::Result))
115
+ res.token.should == 'token'
116
+ res.results.should == ['hello', 'you']
117
+ end
167
118
 
168
- it "should call on_exception Procs defined in a subclass with the correct arguments" do
169
- flexmock(RightScale::Log).should_receive(:error).once
170
- actor = Bar.new
171
- @registry.register(actor, nil)
172
- req = RightScale::Request.new('/bar/i_kill_you', nil)
173
- @dispatcher.dispatch(req, @header)
174
- called_with = actor.instance_variable_get("@called_with")
175
- called_with[0].should == :i_kill_you
176
- called_with[1].should == req
177
- called_with[2].should be_kind_of(RuntimeError)
178
- called_with[2].message.should == 'I kill you!'
179
- end
119
+ it "should dispatch a request with required arity" do
120
+ req = RightScale::Request.new('/foo/bar2', 'you', :token => 'token')
121
+ res = @dispatcher.dispatch(req)
122
+ res.should(be_kind_of(RightScale::Result))
123
+ res.token.should == 'token'
124
+ res.results.should == ['hello', 'you', req]
125
+ end
180
126
 
181
- it "should call on_exception Procs defined in a subclass in the scope of the actor" do
182
- flexmock(RightScale::Log).should_receive(:error).once
183
- actor = Bar.new
184
- @registry.register(actor, nil)
185
- req = RightScale::Request.new('/bar/i_kill_you', nil)
186
- @dispatcher.dispatch(req, @header)
187
- actor.instance_variable_get("@scope").should == actor
188
- end
127
+ it "should dispatch a request to the default action" do
128
+ req = RightScale::Request.new('/foo', 'you', :token => 'token')
129
+ res = @dispatcher.dispatch(req)
130
+ res.should(be_kind_of(RightScale::Result))
131
+ res.token.should == req.token
132
+ res.results.should == ['hello', 'you']
133
+ end
189
134
 
190
- it "should log error if something goes wrong" do
191
- RightScale::Log.should_receive(:error).once
192
- req = RightScale::Request.new('/foo/i_kill_you', nil)
193
- @dispatcher.dispatch(req, @header)
194
- end
135
+ it "should return nil for successful push" do
136
+ req = RightScale::Push.new('/foo', 'you', :token => 'token')
137
+ res = @dispatcher.dispatch(req)
138
+ res.should be_nil
139
+ end
195
140
 
196
- it "should reject requests whose time-to-live has expired" do
197
- flexmock(Time).should_receive(:now).and_return(Time.at(1000000)).by_default
198
- flexmock(RightScale::Log).should_receive(:info).once.with(on {|arg| arg =~ /REJECT EXPIRED.*TTL 2 sec ago/})
199
- @broker.should_receive(:publish).never
200
- @dispatcher = RightScale::Dispatcher.new(@agent, @cache)
201
- @dispatcher.em = EMMock
202
- req = RightScale::Push.new('/foo/bar', 'you', :expires_at => @now.to_i + 8)
203
- flexmock(Time).should_receive(:now).and_return(@now += 10)
204
- @dispatcher.dispatch(req, @header).should be_nil
205
- end
141
+ it "should handle custom prefixes" do
142
+ @registry.register(Foo.new, 'umbongo')
143
+ req = RightScale::Request.new('/umbongo/bar', 'you')
144
+ res = @dispatcher.dispatch(req)
145
+ res.should(be_kind_of(RightScale::Result))
146
+ res.token.should == req.token
147
+ res.results.should == ['hello', 'you']
148
+ end
206
149
 
207
- it "should send non-delivery result if Request is rejected because its time-to-live has expired" do
208
- flexmock(Time).should_receive(:now).and_return(Time.at(1000000)).by_default
209
- flexmock(RightScale::Log).should_receive(:info).once.with(on {|arg| arg =~ /REJECT EXPIRED/})
210
- @broker.should_receive(:publish).with(hsh(:name => @response_queue),
211
- on {|arg| arg.class == RightScale::Result &&
212
- arg.to == @response_queue &&
213
- arg.results.non_delivery? &&
214
- arg.results.content == RightScale::OperationResult::TTL_EXPIRATION},
215
- hsh(:persistent => true, :mandatory => true)).once
216
- @dispatcher = RightScale::Dispatcher.new(@agent, @cache)
217
- @dispatcher.em = EMMock
218
- req = RightScale::Request.new('/foo/bar', 'you', {:reply_to => @response_queue, :expires_at => @now.to_i + 8})
219
- flexmock(Time).should_receive(:now).and_return(@now += 10)
220
- @dispatcher.dispatch(req, @header).should be_nil
221
- end
150
+ it "should raise exception if actor is unknown" do
151
+ req = RightScale::Request.new('/bad', 'you', :token => 'token')
152
+ lambda { @dispatcher.dispatch(req) }.should raise_error(RightScale::Dispatcher::InvalidRequestType)
153
+ end
222
154
 
223
- it "should send error result instead of non-delivery if agent does not know about non-delivery" do
224
- flexmock(Time).should_receive(:now).and_return(Time.at(1000000)).by_default
225
- flexmock(RightScale::Log).should_receive(:info).once.with(on {|arg| arg =~ /REJECT EXPIRED/})
226
- @broker.should_receive(:publish).with(hsh(:name => @response_queue),
227
- on {|arg| arg.class == RightScale::Result &&
228
- arg.to == "rs-mapper-1-1" &&
229
- arg.results.error? &&
230
- arg.results.content =~ /Could not deliver/},
231
- hsh(:persistent => true, :mandatory => true)).once
232
- @dispatcher = RightScale::Dispatcher.new(@agent, @cache)
233
- @dispatcher.em = EMMock
234
- req = RightScale::Request.new('/foo/bar', 'you', {:reply_to => "rs-mapper-1-1", :expires_at => @now.to_i + 8}, [12, 13])
235
- flexmock(Time).should_receive(:now).and_return(@now += 10)
236
- @dispatcher.dispatch(req, @header).should be_nil
237
- end
155
+ it "should raise exception if actor method is unknown" do
156
+ req = RightScale::Request.new('/foo/bar-none', 'you', :token => 'token')
157
+ lambda { @dispatcher.dispatch(req) }.should raise_error(RightScale::Dispatcher::InvalidRequestType)
158
+ end
238
159
 
239
- it "should not reject requests whose time-to-live has not expired" do
240
- flexmock(Time).should_receive(:now).and_return(Time.at(1000000)).by_default
241
- @dispatcher = RightScale::Dispatcher.new(@agent, @cache)
242
- @dispatcher.em = EMMock
243
- req = RightScale::Request.new('/foo/bar', 'you', :expires_at => @now.to_i + 11)
244
- flexmock(Time).should_receive(:now).and_return(@now += 10)
245
- res = @dispatcher.dispatch(req, @header)
246
- res.should(be_kind_of(RightScale::Result))
247
- res.token.should == req.token
248
- res.results.should == ['hello', 'you']
249
- end
160
+ it "should call the on_exception callback if something goes wrong" do
161
+ @log.should_receive(:error).once
162
+ req = RightScale::Request.new('/foo/i_kill_you', nil)
163
+ flexmock(@actor).should_receive(:handle_exception).with(:i_kill_you, req, Exception).once
164
+ res = @dispatcher.dispatch(req)
165
+ res.results.error?.should be_true
166
+ (res.results.content =~ /Could not handle \/foo\/i_kill_you request/).should be_true
167
+ end
250
168
 
251
- it "should not check age of requests with time-to-live check disabled" do
252
- @dispatcher = RightScale::Dispatcher.new(@agent, @cache)
253
- @dispatcher.em = EMMock
254
- req = RightScale::Request.new('/foo/bar', 'you', :expires_at => 0)
255
- res = @dispatcher.dispatch(req, @header)
256
- res.should(be_kind_of(RightScale::Result))
257
- res.token.should == req.token
258
- res.results.should == ['hello', 'you']
259
- end
169
+ it "should call on_exception Procs defined in a subclass with the correct arguments" do
170
+ @log.should_receive(:error).once
171
+ actor = Bar.new
172
+ @registry.register(actor, nil)
173
+ req = RightScale::Request.new('/bar/i_kill_you', nil)
174
+ @dispatcher.dispatch(req)
175
+ called_with = actor.instance_variable_get("@called_with")
176
+ called_with[0].should == :i_kill_you
177
+ called_with[1].should == req
178
+ called_with[2].should be_kind_of(RuntimeError)
179
+ called_with[2].message.should == 'I kill you!'
180
+ end
181
+
182
+ it "should call on_exception Procs defined in a subclass in the scope of the actor" do
183
+ @log.should_receive(:error).once
184
+ actor = Bar.new
185
+ @registry.register(actor, nil)
186
+ req = RightScale::Request.new('/bar/i_kill_you', nil)
187
+ @dispatcher.dispatch(req)
188
+ actor.instance_variable_get("@scope").should == actor
189
+ end
260
190
 
261
- it "should reject duplicate requests" do
262
- flexmock(RightScale::Log).should_receive(:info).once.with(on {|arg| arg =~ /REJECT DUP/})
263
- EM.run do
191
+ it "should log error if dispatch fails" do
192
+ RightScale::Log.should_receive(:error).once
193
+ req = RightScale::Request.new('/foo/i_kill_you', nil)
194
+ @dispatcher.dispatch(req)
195
+ end
196
+
197
+ it "should reject requests whose time-to-live has expired" do
198
+ flexmock(Time).should_receive(:now).and_return(Time.at(1000000)).by_default
199
+ @log.should_receive(:info).once.with(on {|arg| arg =~ /REJECT EXPIRED.*TTL 2 sec ago/})
264
200
  @dispatcher = RightScale::Dispatcher.new(@agent, @cache)
265
- @dispatcher.em = EMMock
266
- req = RightScale::Request.new('/foo/bar_non', 1, :token => "try")
267
- @cache.store(req.token, nil)
268
- @dispatcher.dispatch(req, @header).should be_nil
269
- EM.stop
201
+ req = RightScale::Push.new('/foo/bar', 'you', :expires_at => @now.to_i + 8)
202
+ flexmock(Time).should_receive(:now).and_return(@now += 10)
203
+ @dispatcher.dispatch(req).should be_nil
270
204
  end
271
- end
272
205
 
273
- it "should reject duplicate retry requests" do
274
- flexmock(RightScale::Log).should_receive(:info).once.with(on {|arg| arg =~ /REJECT RETRY DUP/})
275
- EM.run do
206
+ it "should return non-delivery result if Request is rejected because its time-to-live has expired" do
207
+ flexmock(Time).should_receive(:now).and_return(Time.at(1000000)).by_default
208
+ @log.should_receive(:info).once.with(on {|arg| arg =~ /REJECT EXPIRED/})
276
209
  @dispatcher = RightScale::Dispatcher.new(@agent, @cache)
277
- @dispatcher.em = EMMock
278
- req = RightScale::Request.new('/foo/bar_non', 1, :token => "try")
279
- req.tries.concat(["try1", "try2"])
280
- @cache.store("try2", nil)
281
- @dispatcher.dispatch(req, @header).should be_nil
282
- EM.stop
210
+ req = RightScale::Request.new('/foo/bar', 'you', {:reply_to => @response_queue, :expires_at => @now.to_i + 8})
211
+ flexmock(Time).should_receive(:now).and_return(@now += 10)
212
+ res = @dispatcher.dispatch(req)
213
+ res.results.non_delivery?.should be_true
214
+ res.results.content.should == RightScale::OperationResult::TTL_EXPIRATION
283
215
  end
284
- end
285
216
 
286
- it "should not reject non-duplicate requests" do
287
- EM.run do
217
+ it "should return error result instead of non-delivery if agent does not know about non-delivery" do
218
+ flexmock(Time).should_receive(:now).and_return(Time.at(1000000)).by_default
219
+ @log.should_receive(:info).once.with(on {|arg| arg =~ /REJECT EXPIRED/})
288
220
  @dispatcher = RightScale::Dispatcher.new(@agent, @cache)
289
- @dispatcher.em = EMMock
290
- req = RightScale::Request.new('/foo/bar_non', 1, :token => "try")
291
- req.tries.concat(["try1", "try2"])
292
- @cache.store("try3", nil)
293
- @dispatcher.dispatch(req, @header).should_not be_nil
294
- EM.stop
221
+ req = RightScale::Request.new('/foo/bar', 'you', {:reply_to => "rs-mapper-1-1", :expires_at => @now.to_i + 8}, [12, 13])
222
+ flexmock(Time).should_receive(:now).and_return(@now += 10)
223
+ res = @dispatcher.dispatch(req)
224
+ res.results.error?.should be_true
225
+ res.results.content.should =~ /Could not deliver/
295
226
  end
296
- end
297
227
 
298
- it "should not reject duplicate idempotent requests" do
299
- EM.run do
228
+ it "should not reject requests whose time-to-live has not expired" do
229
+ flexmock(Time).should_receive(:now).and_return(Time.at(1000000)).by_default
300
230
  @dispatcher = RightScale::Dispatcher.new(@agent, @cache)
301
- @dispatcher.em = EMMock
302
- req = RightScale::Request.new('/foo/bar', 'you', :token => "try")
303
- @cache.store(req.token, nil)
304
- @dispatcher.dispatch(req, @header).should_not be_nil
305
- EM.stop
231
+ req = RightScale::Request.new('/foo/bar', 'you', :expires_at => @now.to_i + 11)
232
+ flexmock(Time).should_receive(:now).and_return(@now += 10)
233
+ res = @dispatcher.dispatch(req)
234
+ res.should(be_kind_of(RightScale::Result))
235
+ res.token.should == req.token
236
+ res.results.should == ['hello', 'you']
306
237
  end
307
- end
308
238
 
309
- it "should not check for duplicates if duplicate checking is disabled" do
310
- EM.run do
311
- @dispatcher = RightScale::Dispatcher.new(@agent, dispatched_cache = nil)
312
- @dispatcher.em = EMMock
313
- req = RightScale::Request.new('/foo/bar_non', 1, :token => "try")
314
- req.tries.concat(["try1", "try2"])
315
- @dispatcher.instance_variable_get(:@dispatched_cache).should be_nil
316
- @dispatcher.dispatch(req, @header).should_not be_nil
317
- EM.stop
239
+ it "should not check age of requests with time-to-live check disabled" do
240
+ @dispatcher = RightScale::Dispatcher.new(@agent, @cache)
241
+ req = RightScale::Request.new('/foo/bar', 'you', :expires_at => 0)
242
+ res = @dispatcher.dispatch(req)
243
+ res.should(be_kind_of(RightScale::Result))
244
+ res.token.should == req.token
245
+ res.results.should == ['hello', 'you']
318
246
  end
319
- end
320
247
 
321
- it "should not check for duplicates if actor method is idempotent" do
322
- EM.run do
323
- @dispatcher = RightScale::Dispatcher.new(@agent, dispatched_cache = nil)
324
- @dispatcher.em = EMMock
325
- req = RightScale::Request.new('/foo/bar', 1, :token => "try")
326
- req.tries.concat(["try1", "try2"])
327
- @dispatcher.instance_variable_get(:@dispatched_cache).should be_nil
328
- @dispatcher.dispatch(req, @header).should_not be_nil
329
- EM.stop
248
+ it "should reject duplicate request by raising exception" do
249
+ @log.should_receive(:info).once.with(on {|arg| arg =~ /REJECT DUP/})
250
+ EM.run do
251
+ @dispatcher = RightScale::Dispatcher.new(@agent, @cache)
252
+ req = RightScale::Request.new('/foo/bar_non', 1, :token => "try")
253
+ @cache.store(req.token)
254
+ lambda { @dispatcher.dispatch(req) }.should raise_error(RightScale::Dispatcher::DuplicateRequest)
255
+ EM.stop
256
+ end
330
257
  end
331
- end
332
258
 
333
- it "should return dispatch age of youngest unfinished request" do
334
- @header.should_receive(:ack).never
335
- @dispatcher.em = EMMockNoCallback
336
- @dispatcher.dispatch_age.should be_nil
337
- @dispatcher.dispatch(RightScale::Push.new('/foo/bar', 'you'), @header)
338
- @dispatcher.dispatch_age.should == 0
339
- @dispatcher.dispatch(RightScale::Request.new('/foo/bar', 'you'), @header)
340
- flexmock(Time).should_receive(:now).and_return(@now += 100)
341
- @dispatcher.dispatch_age.should == 100
342
- end
259
+ it "should reject duplicate request from a retry by raising exception" do
260
+ @log.should_receive(:info).once.with(on {|arg| arg =~ /REJECT RETRY DUP/})
261
+ EM.run do
262
+ @dispatcher = RightScale::Dispatcher.new(@agent, @cache)
263
+ req = RightScale::Request.new('/foo/bar_non', 1, :token => "try")
264
+ req.tries.concat(["try1", "try2"])
265
+ @cache.store("try2")
266
+ lambda { @dispatcher.dispatch(req) }.should raise_error(RightScale::Dispatcher::DuplicateRequest)
267
+ EM.stop
268
+ end
269
+ end
343
270
 
344
- it "should return dispatch age of nil if all requests finished" do
345
- @dispatcher.dispatch_age.should be_nil
346
- @dispatcher.dispatch(RightScale::Request.new('/foo/bar', 'you'), @header)
347
- flexmock(Time).should_receive(:now).and_return(@now += 100)
348
- @dispatcher.dispatch_age.should be_nil
349
- end
271
+ it "should not reject non-duplicate requests" do
272
+ EM.run do
273
+ @dispatcher = RightScale::Dispatcher.new(@agent, @cache)
274
+ req = RightScale::Request.new('/foo/bar_non', 1, :token => "try")
275
+ req.tries.concat(["try1", "try2"])
276
+ @cache.store("try3")
277
+ @dispatcher.dispatch(req).should_not be_nil
278
+ EM.stop
279
+ end
280
+ end
350
281
 
351
- it "should ack request even if fail while dispatching" do
352
- RightScale::Log.should_receive(:error).and_raise(Exception).once
353
- req = RightScale::Request.new('/foo/i_kill_you', nil)
354
- lambda { @dispatcher.dispatch(req, @header) }.should raise_error(Exception)
355
- end
282
+ it "should not reject duplicate idempotent requests" do
283
+ EM.run do
284
+ @dispatcher = RightScale::Dispatcher.new(@agent, @cache)
285
+ req = RightScale::Request.new('/foo/bar', 'you', :token => "try")
286
+ @cache.store(req.token)
287
+ @dispatcher.dispatch(req).should_not be_nil
288
+ EM.stop
289
+ end
290
+ end
356
291
 
357
- it "should not attempt to ack request if fail while dispatching and there is no header" do
358
- @header.should_receive(:ack).never
359
- RightScale::Log.should_receive(:error).and_raise(Exception).once
360
- req = RightScale::Request.new('/foo/i_kill_you', nil)
361
- lambda { @dispatcher.dispatch(req, nil) }.should raise_error(Exception)
362
- end
292
+ it "should not check for duplicates if duplicate checking is disabled" do
293
+ EM.run do
294
+ @dispatcher = RightScale::Dispatcher.new(@agent, dispatched_cache = nil)
295
+ req = RightScale::Request.new('/foo/bar_non', 1, :token => "try")
296
+ req.tries.concat(["try1", "try2"])
297
+ @dispatcher.instance_variable_get(:@dispatched_cache).should be_nil
298
+ @dispatcher.dispatch(req).should_not be_nil
299
+ EM.stop
300
+ end
301
+ end
363
302
 
364
- it "should ack request even if fail while doing final setup for processing request" do
365
- @dispatcher.em = EMMock
366
- flexmock(EMMock).should_receive(:defer).and_raise(Exception).once
367
- req = RightScale::Request.new('/foo/bar', 'you')
368
- lambda { @dispatcher.dispatch(req, @header) }.should raise_error(Exception)
369
- end
303
+ it "should not check for duplicates if actor method is idempotent" do
304
+ EM.run do
305
+ @dispatcher = RightScale::Dispatcher.new(@agent, dispatched_cache = nil)
306
+ req = RightScale::Request.new('/foo/bar', 1, :token => "try")
307
+ req.tries.concat(["try1", "try2"])
308
+ @dispatcher.instance_variable_get(:@dispatched_cache).should be_nil
309
+ @dispatcher.dispatch(req).should_not be_nil
310
+ EM.stop
311
+ end
312
+ end
370
313
 
371
- it "should not attempt to ack request if fail while doing final setup for processing request and there is no header" do
372
- @header.should_receive(:ack).never
373
- @dispatcher.em = EMMock
374
- flexmock(EMMock).should_receive(:defer).and_raise(Exception).once
375
- req = RightScale::Request.new('/foo/bar', 'you')
376
- lambda { @dispatcher.dispatch(req, nil) }.should raise_error(Exception)
377
- end
314
+ it "should return error result if dispatch fails" do
315
+ @log.should_receive(:error).with(/Could not handle/, Exception, :trace).once
316
+ req = RightScale::Request.new('/foo/i_kill_you', nil)
317
+ res = @dispatcher.dispatch(req)
318
+ res.results.error?.should be_true
319
+ end
378
320
 
379
- it "should not attempt to ack request if dispatch a request and there is no header" do
380
- @header.should_receive(:ack).never
381
- req = RightScale::Request.new('/foo/bar', 'you', :token => 'token')
382
- @dispatcher.dispatch(req, nil)
383
321
  end
384
322
 
385
323
  end # RightScale::Dispatcher