rservicebus 0.1.32 → 0.1.33

Sign up to get free protection for your applications and to get access to all the features.
data/lib/rservicebus.rb CHANGED
@@ -29,6 +29,7 @@ require "rservicebus/UserMessage/WithPayload"
29
29
 
30
30
  require "rservicebus/StateManager"
31
31
  require "rservicebus/CronManager"
32
+ require "rservicebus/CircuitBreaker"
32
33
 
33
34
  require "rservicebus/AppResource"
34
35
 
@@ -0,0 +1,100 @@
1
+ module RServiceBus
2
+
3
+ #Considered just holding in here when the circuit broke, but thought there may be other things the system might want
4
+ # to do - not that I could think of anything off the top of my head.
5
+
6
+ class MessageArrivedWhileCricuitBroken<StandardError
7
+ end
8
+
9
+ #An implementation of Michael Nygard's Circuit Breaker pattern.
10
+ class CircuitBreaker
11
+
12
+ def reset
13
+ @broken = false
14
+
15
+ @numberOfFailures = 0
16
+ @timeOfFirstFailure = nil
17
+
18
+ @timeToBreak = nil
19
+ @timeToReset = nil
20
+ end
21
+
22
+ def initialize( host )
23
+ @host = host
24
+ @maxNumberOfFailures = RServiceBus.getValue( "RSBCB_MAX", 5 )
25
+ @secondsToBreak = RServiceBus.getValue( "RSBCB_SECONDS_TO_BREAK", 60 ).to_i
26
+ @secondsToReset = RServiceBus.getValue( "RSBCB_SECONDS_TO_RESET", 60 ).to_i
27
+ @resetOnSuccess = RServiceBus.getValue( "RSBCB_RESET_ON_SUCCESS", false )
28
+
29
+ self.reset
30
+ end
31
+
32
+ ####### Public Interface
33
+ # Broken will be called before processing a message.
34
+ # => Broken will be called before Failure
35
+ def Broken
36
+ if !@timeToReset.nil? && Time.now > @timeToReset then
37
+ self.reset
38
+ end
39
+
40
+ return @broken
41
+ end
42
+
43
+ def Live
44
+ return !self.Broken
45
+ end
46
+
47
+
48
+ ## This should be called less than success.
49
+ ## If there is a failure, then taking a bit longer gives time to settle.
50
+ def Failure
51
+ self.messageArrived
52
+
53
+
54
+ ##logFirstFailure
55
+ if @numberOfFailures == 0
56
+ @numberOfFailures = 1
57
+ @timeOfFirstFailure = Time.now
58
+ @timeToBreak = @timeOfFirstFailure + @secondsToBreak
59
+ else
60
+ @numberOfFailures = @numberOfFailures + 1
61
+ end
62
+
63
+
64
+ ##checkToBreakCircuit
65
+ if @numberOfFailures >= @maxNumberOfFailures then
66
+ self.breakCircuit
67
+ end
68
+ end
69
+
70
+ def Success
71
+ if @resetOnSuccess == true then
72
+ self.reset
73
+ return
74
+ end
75
+
76
+ self.messageArrived
77
+ end
78
+
79
+
80
+
81
+ ######
82
+ protected
83
+
84
+ def messageArrived
85
+ if !@timeToBreak.nil? && Time.now > @timeToBreak then
86
+ self.reset
87
+ end
88
+
89
+ raise MessageArrivedWhileCricuitBroken if @broken == true
90
+ end
91
+
92
+
93
+ def breakCircuit
94
+ @broken = true
95
+ @timeToReset = Time.now + @secondsToReset
96
+ end
97
+
98
+ end
99
+
100
+ end
@@ -9,7 +9,7 @@ module RServiceBus
9
9
  end
10
10
  class PropertyNotSet<StandardError
11
11
  end
12
-
12
+
13
13
  #Host process for rservicebus
14
14
  class Host
15
15
 
@@ -65,8 +65,14 @@ module RServiceBus
65
65
  return self;
66
66
  end
67
67
 
68
-
69
-
68
+ #Thin veneer for Configuring Cron
69
+ #
70
+ def configureCircuitBreaker
71
+ @circuitBreaker = CircuitBreaker.new( self )
72
+ return self;
73
+ end
74
+
75
+
70
76
  #Thin veneer for Configuring external resources
71
77
  #
72
78
  def configureMonitors
@@ -166,6 +172,7 @@ module RServiceBus
166
172
  .configureAppResource()
167
173
  .configureStateManager()
168
174
  .configureCronManager()
175
+ .configureCircuitBreaker()
169
176
  .configureMonitors()
170
177
  .loadHandlers()
171
178
  .connectToMq()
@@ -200,7 +207,7 @@ module RServiceBus
200
207
  statOutputCountdown = 0
201
208
  messageLoop = true
202
209
  retries = @config.maxRetries
203
-
210
+
204
211
  while messageLoop do
205
212
  #Popping a msg off the queue should not be in the message handler, as it affects retry
206
213
  begin
@@ -212,6 +219,11 @@ module RServiceBus
212
219
  end
213
220
  statOutputCountdown = statOutputCountdown - 1
214
221
 
222
+ if @circuitBreaker.Broken then
223
+ sleep 0.5
224
+ next
225
+ end
226
+
215
227
  body = @mq.pop
216
228
  begin
217
229
  @stats.incTotalProcessed
@@ -264,6 +276,8 @@ module RServiceBus
264
276
  @mq.returnToQueue
265
277
  else
266
278
 
279
+ @circuitBreaker.Failure
280
+
267
281
  @stats.incTotalErrored
268
282
  if e.class.name == "Beanstalk::NotConnected" then
269
283
  puts "Lost connection to beanstalkd."
@@ -302,10 +316,13 @@ module RServiceBus
302
316
  @queueForMsgsToBeSentOnComplete = nil
303
317
 
304
318
  @queueForMsgsToBeSentOnComplete = Array.new
305
- @cronManager.Run
319
+ @cronManager.Run
306
320
  self.sendQueuedMsgs
307
321
  @queueForMsgsToBeSentOnComplete = nil
308
322
 
323
+
324
+ @circuitBreaker.Success
325
+
309
326
  rescue Exception => e
310
327
  if e.message == "SIGTERM" then
311
328
  puts "Exiting on request ..."
@@ -15,6 +15,8 @@ module RServiceBus
15
15
  end
16
16
 
17
17
  def RServiceBus.log(string, ver=false)
18
+ return unless ENV['TESTING'].nil?
19
+
18
20
  type = ver ? "VERB" : "INFO"
19
21
  # if @config.verbose || !ver then
20
22
  timestamp = Time.new.strftime( "%Y-%m-%d %H:%M:%S" )
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rservicebus
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.32
4
+ version: 0.1.33
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ date: 2013-10-03 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: uuidtools
16
- requirement: &70245751164860 !ruby/object:Gem::Requirement
16
+ requirement: &70168920560860 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70245751164860
24
+ version_requirements: *70168920560860
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: json
27
- requirement: &70245751163360 !ruby/object:Gem::Requirement
27
+ requirement: &70168920555700 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70245751163360
35
+ version_requirements: *70168920555700
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: beanstalk-client
38
- requirement: &70245751178000 !ruby/object:Gem::Requirement
38
+ requirement: &70168920924560 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *70245751178000
46
+ version_requirements: *70168920924560
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: fluiddb
49
- requirement: &70245751176680 !ruby/object:Gem::Requirement
49
+ requirement: &70168920923940 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '0'
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *70245751176680
57
+ version_requirements: *70168920923940
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: parse-cron
60
- requirement: &70245751175200 !ruby/object:Gem::Requirement
60
+ requirement: &70168920923200 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,7 +65,7 @@ dependencies:
65
65
  version: '0'
66
66
  type: :runtime
67
67
  prerelease: false
68
- version_requirements: *70245751175200
68
+ version_requirements: *70168920923200
69
69
  description: A Ruby interpretation of NServiceBus
70
70
  email: guy@guyirvine.com
71
71
  executables:
@@ -95,6 +95,7 @@ files:
95
95
  - lib/rservicebus/AppResource/SmbFile.rb
96
96
  - lib/rservicebus/AppResource.rb
97
97
  - lib/rservicebus/Audit.rb
98
+ - lib/rservicebus/CircuitBreaker.rb
98
99
  - lib/rservicebus/Config.rb
99
100
  - lib/rservicebus/ConfigureAppResource.rb
100
101
  - lib/rservicebus/ConfigureMonitor.rb