Skip to content

Commit e501e50

Browse files
committed
Cleanups and logger feature.
1 parent 93f587a commit e501e50

File tree

6 files changed

+98
-47
lines changed

6 files changed

+98
-47
lines changed

Gemfile.lock

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ GIT
77
PATH
88
remote: .
99
specs:
10-
tribe (0.6.0)
10+
tribe (0.6.1)
1111
workers (~> 0.4)
1212

1313
GEM

README.md

+11
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,17 @@ To support in the tens of thousands, hundreds of thousands, or potentially milli
471471
# The pool size is back to the default size.
472472
puts "Pool size (after): #{Workers.pool.size}"
473473

474+
## Logging
475+
476+
Tribe provides a shared instance of ````Logger```` for your convenience:
477+
478+
Tribe.logger
479+
480+
Every actor also has access to it through the ````logger```` convenience method.
481+
482+
By default, the logger will log to STDOUT.
483+
You should change this to a file in your application.
484+
474485
## Debugging
475486

476487
Tribe is written in pure Ruby so it will work with all existing debuggers that support Ruby & threads.

lib/tribe.rb

+29-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
require 'set'
2+
require 'logger'
3+
require 'thread'
24

35
require 'workers'
46

@@ -16,11 +18,36 @@
1618
require 'tribe/root'
1719

1820
module Tribe
21+
@lock = Monitor.new
22+
23+
class << self
24+
attr_reader :lock
25+
end
26+
1927
def self.registry
20-
return @registry ||= Tribe::Registry.new
28+
@lock.synchronize do
29+
@registry ||= Tribe::Registry.new
30+
end
2131
end
2232

2333
def self.root
24-
@root ||= Tribe::Root.new(:name => 'root', :permit_root => true)
34+
@lock.synchronize do
35+
@root ||= Tribe::Root.new(:name => 'root', :permit_root => true)
36+
end
37+
end
38+
39+
def self.logger
40+
@lock.synchronize do
41+
@logger
42+
end
43+
end
44+
45+
def self.logger=(val)
46+
@lock.synchronize do
47+
@logger = val
48+
end
2549
end
2650
end
51+
52+
Tribe.logger = Logger.new(STDOUT)
53+
Tribe.logger.level = Logger::DEBUG

lib/tribe/actable.rb

+54-44
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,26 @@ module Tribe
22
module Actable
33
include Workers::Helpers
44

5+
private
6+
57
#
68
# Initialization method.
79
# Notes: Call this in your constructor.
810
#
911

10-
private
11-
1212
def init_actable(options = {})
1313
# Symbols aren't GCed in JRuby so force string names.
1414
if options[:name] && !options[:name].is_a?(String)
1515
raise Tribe::ActorNameError.new('Name must be a string.')
1616
end
1717

18-
@logger = Workers::LogProxy.new(options[:logger])
1918
@_actable = Tribe::ActorState.new
19+
2020
@_actable.dedicated = options[:dedicated] || false
2121
@_actable.pool = @_actable.dedicated ? Workers::Pool.new(:size => 1) : (options[:pool] || Workers.pool)
2222
@_actable.mailbox = Tribe::Mailbox.new(@_actable.pool)
2323
@_actable.registry = options[:registry] || Tribe.registry
24+
@_actable.logger = Workers::LogProxy.new(options[:logger] || Tribe.logger)
2425
@_actable.scheduler = options[:scheduler] || Workers.scheduler
2526
@_actable.name = options[:name]
2627
@_actable.parent = options[:parent]
@@ -47,38 +48,21 @@ def deliver_event!(event)
4748
process_events
4849
end
4950

50-
return nil
51+
nil
5152
end
5253

5354
def direct_message!(command, data = nil, src = nil)
5455
deliver_event!(Tribe::Event.new(command, data, src))
5556

56-
return nil
57-
end
58-
59-
def message!(dest, command, data = nil)
60-
event = Tribe::Event.new(command, data, self)
61-
62-
dest.deliver_event!(event)
63-
64-
return nil
65-
end
66-
67-
def future!(dest, command, data = nil)
68-
event = Tribe::Event.new(command, data, self)
69-
event.future = future = Tribe::Future.new(self)
70-
71-
dest.deliver_event!(event)
72-
73-
return future
57+
nil
7458
end
7559

7660
def shutdown!
77-
return direct_message!(:__shutdown__)
61+
direct_message!(:__shutdown__)
7862
end
7963

8064
def perform!(&block)
81-
return direct_message!(:__perform__, block)
65+
direct_message!(:__perform__, block)
8266
end
8367

8468
def spawn!(klass, actor_options = {}, spawn_options = {})
@@ -102,7 +86,7 @@ def spawn!(klass, actor_options = {}, spawn_options = {})
10286
@_actable.supervisees.add(child)
10387
end
10488

105-
return child
89+
child
10690
end
10791

10892
def alive?
@@ -114,23 +98,27 @@ def dead?
11498
end
11599

116100
def name
117-
return @_actable.name
101+
@_actable.name
118102
end
119103

120104
def identifier
121-
return @_actable.name ? "#{object_id}:#{@_actable.name}" : object_id
105+
@_actable.name ? "#{object_id}:#{@_actable.name}" : object_id
122106
end
123107

124108
def exception
125-
return @_actable.exception
109+
@_actable.exception
126110
end
127111

128112
def registry
129-
return @_actable.registry
113+
@_actable.registry
130114
end
131115

132116
def pool
133-
return @_actable.pool
117+
@_actable.pool
118+
end
119+
120+
def logger
121+
@_actable.logger
134122
end
135123

136124
#
@@ -179,7 +167,7 @@ def process_events
179167
process_events
180168
end
181169

182-
return nil
170+
nil
183171
end
184172

185173
def event_handler(event)
@@ -220,7 +208,7 @@ def custom_event_handler(event)
220208
@_actable.active_event = nil
221209
end
222210

223-
return nil
211+
nil
224212
end
225213

226214
def initialize_handler(event)
@@ -236,9 +224,14 @@ def exception_handler(exception)
236224
@_actable.children.clear
237225
@_actable.supervisees.clear
238226

227+
log_exception_handler(exception)
239228
on_exception(Event.new(:exception, {:exception => exception}))
240229

241-
return nil
230+
nil
231+
end
232+
233+
def log_exception_handler(exception)
234+
logger.error("EXCEPTION: #{exception.message}\n#{exception.backtrace.join("\n")}\n--")
242235
end
243236

244237
def shutdown_handler(event)
@@ -252,13 +245,13 @@ def shutdown_handler(event)
252245

253246
on_shutdown(Event.new(:shutdown, {}))
254247

255-
return nil
248+
nil
256249
end
257250

258251
def perform_handler(event)
259252
event.data.call
260253

261-
return nil
254+
nil
262255
end
263256

264257
def cleanup_handler(exception = nil)
@@ -268,7 +261,7 @@ def cleanup_handler(exception = nil)
268261
@_actable.registry.unregister(self)
269262
@_actable.timers.each { |t| t.cancel } if @_actable.timers
270263

271-
return nil
264+
nil
272265
end
273266

274267
def child_died_handler(child, exception)
@@ -281,7 +274,7 @@ def child_died_handler(child, exception)
281274
raise Tribe::ActorChildDied.new("#{child.identifier} died.")
282275
end
283276

284-
return nil
277+
nil
285278
end
286279

287280
def child_shutdown_handler(child)
@@ -290,14 +283,14 @@ def child_shutdown_handler(child)
290283

291284
on_child_shutdown(Event.new(:child_shutdown, {:child => child}))
292285

293-
return nil
286+
nil
294287
end
295288

296289
def parent_died_handler(parent, exception)
297290
on_parent_died(Event.new(:parent_died, {:parent => parent, :exception => exception}))
298291
raise Tribe::ActorParentDied.new("#{parent.identifier} died.")
299292

300-
return nil
293+
nil
301294
end
302295

303296
#
@@ -307,6 +300,23 @@ def parent_died_handler(parent, exception)
307300

308301
private
309302

303+
def message!(dest, command, data = nil)
304+
event = Tribe::Event.new(command, data, self)
305+
306+
dest.deliver_event!(event)
307+
308+
nil
309+
end
310+
311+
def future!(dest, command, data = nil)
312+
event = Tribe::Event.new(command, data, self)
313+
event.future = future = Tribe::Future.new(self)
314+
315+
dest.deliver_event!(event)
316+
317+
future
318+
end
319+
310320
def timer!(delay, command, data = nil)
311321
timer = Workers::Timer.new(delay, :scheduler => @_actable.scheduler) do
312322
@_actable.timers.delete(timer)
@@ -315,7 +325,7 @@ def timer!(delay, command, data = nil)
315325

316326
@_actable.timers.add(timer)
317327

318-
return timer
328+
timer
319329
end
320330

321331
def periodic_timer!(delay, command, data = nil)
@@ -329,19 +339,19 @@ def periodic_timer!(delay, command, data = nil)
329339

330340
@_actable.timers.add(timer)
331341

332-
return timer
342+
timer
333343
end
334344

335345
def forward!(dest)
336346
dest.deliver_event!(@_actable.active_event)
337347
@_actable.active_event = nil
338348

339-
return nil
349+
nil
340350
end
341351

342352
# Wrap blocking code using this method to automatically expand/contract the pool.
343-
# This way you avoid potential deadlock with blocking code.
344-
# Not needed for dedicated actors since they already have their own thread.
353+
# This way you avoid potential thread starvation. Not needed for dedicated actors
354+
# since they already have their own thread.
345355
def blocking!
346356
if @_actable.dedicated
347357
yield

lib/tribe/actor_state.rb

+1
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,6 @@ class ActorState
1212
attr_accessor :children
1313
attr_accessor :supervisees
1414
attr_accessor :exception
15+
attr_accessor :logger
1516
end
1617
end

test/test_helper.rb

+2
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,6 @@ def poll(seconds = 5)
3636
raise 'Poll timeout.' unless yield
3737
end
3838

39+
Tribe.logger = nil
40+
3941
require 'minitest/autorun'

0 commit comments

Comments
 (0)