celluloid 0.16.0 → 0.17.3
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.
- checksums.yaml +4 -4
- data/CHANGES.md +394 -0
- data/LICENSE.txt +1 -1
- data/README.md +28 -15
- data/culture/CONDUCT.md +28 -0
- data/culture/Gemfile +9 -0
- data/culture/LICENSE.txt +22 -0
- data/culture/README.md +22 -0
- data/culture/Rakefile +5 -0
- data/culture/SYNC.md +70 -0
- data/culture/celluloid-culture.gemspec +18 -0
- data/culture/gems/README.md +39 -0
- data/culture/gems/dependencies.yml +85 -0
- data/culture/gems/loader.rb +101 -0
- data/culture/rubocop/README.md +38 -0
- data/culture/rubocop/lint.yml +8 -0
- data/culture/rubocop/metrics.yml +15 -0
- data/culture/rubocop/perf.yml +0 -0
- data/culture/rubocop/rubocop.yml +5 -0
- data/culture/rubocop/style.yml +57 -0
- data/culture/spec/gems_spec.rb +2 -0
- data/culture/spec/spec_helper.rb +0 -0
- data/culture/spec/sync_spec.rb +2 -0
- data/culture/sync.rb +56 -0
- data/culture/tasks/rspec.rake +5 -0
- data/culture/tasks/rubocop.rake +2 -0
- data/examples/basic_usage.rb +49 -0
- data/examples/futures.rb +38 -0
- data/examples/ring.rb +61 -0
- data/examples/simple_pmap.rb +14 -0
- data/examples/stack.rb +47 -0
- data/examples/timers.rb +72 -0
- data/lib/celluloid/actor/manager.rb +7 -0
- data/lib/celluloid/actor/system.rb +163 -0
- data/lib/celluloid/actor.rb +53 -71
- data/lib/celluloid/autostart.rb +1 -1
- data/lib/celluloid/backported.rb +2 -0
- data/lib/celluloid/call/async.rb +16 -0
- data/lib/celluloid/call/block.rb +22 -0
- data/lib/celluloid/call/sync.rb +70 -0
- data/lib/celluloid/calls.rb +24 -114
- data/lib/celluloid/cell.rb +32 -20
- data/lib/celluloid/condition.rb +5 -6
- data/lib/celluloid/core_ext.rb +1 -1
- data/lib/celluloid/current.rb +2 -0
- data/lib/celluloid/debug.rb +1 -0
- data/lib/celluloid/deprecate.rb +21 -0
- data/lib/celluloid/exceptions.rb +22 -16
- data/lib/celluloid/fiber.rb +3 -3
- data/lib/celluloid/future.rb +46 -8
- data/lib/celluloid/group/pool.rb +125 -0
- data/lib/celluloid/group/spawner.rb +68 -0
- data/lib/celluloid/group.rb +61 -0
- data/lib/celluloid/logging.rb +5 -5
- data/lib/celluloid/mailbox/evented.rb +74 -0
- data/lib/celluloid/mailbox.rb +15 -14
- data/lib/celluloid/managed.rb +3 -0
- data/lib/celluloid/notices.rb +15 -0
- data/lib/celluloid/proxies.rb +11 -0
- data/lib/celluloid/proxy/abstract.rb +50 -0
- data/lib/celluloid/proxy/actor.rb +37 -0
- data/lib/celluloid/proxy/async.rb +15 -0
- data/lib/celluloid/proxy/block.rb +28 -0
- data/lib/celluloid/proxy/cell.rb +66 -0
- data/lib/celluloid/proxy/future.rb +20 -0
- data/lib/celluloid/proxy/sync.rb +24 -0
- data/lib/celluloid/rspec.rb +67 -9
- data/lib/celluloid/system_events.rb +69 -14
- data/lib/celluloid/task/fibered.rb +45 -0
- data/lib/celluloid/task/threaded.rb +59 -0
- data/lib/celluloid/{tasks.rb → task.rb} +30 -38
- data/lib/celluloid/test.rb +1 -1
- data/lib/celluloid/thread.rb +6 -1
- data/lib/celluloid/version.rb +3 -0
- data/lib/celluloid.rb +151 -130
- data/spec/celluloid/actor/system_spec.rb +83 -0
- data/spec/celluloid/actor_spec.rb +2 -2
- data/spec/celluloid/block_spec.rb +67 -8
- data/spec/celluloid/calls_spec.rb +28 -23
- data/spec/celluloid/condition_spec.rb +23 -14
- data/spec/celluloid/evented_mailbox_spec.rb +1 -31
- data/spec/celluloid/future_spec.rb +15 -12
- data/spec/celluloid/group/elastic_spec.rb +0 -0
- data/spec/celluloid/group/pool_spec.rb +8 -0
- data/spec/celluloid/group/spawner_spec.rb +17 -0
- data/spec/celluloid/mailbox/evented_spec.rb +40 -0
- data/spec/celluloid/mailbox_spec.rb +1 -3
- data/spec/celluloid/misc/leak_spec.rb +73 -0
- data/spec/celluloid/proxy_spec.rb +33 -0
- data/spec/celluloid/task/fibered_spec.rb +5 -0
- data/spec/celluloid/task/threaded_spec.rb +5 -0
- data/spec/celluloid/timer_spec.rb +14 -16
- data/spec/deprecate/actor_system_spec.rb +72 -0
- data/spec/deprecate/block_spec.rb +52 -0
- data/spec/deprecate/calls_spec.rb +39 -0
- data/spec/deprecate/evented_mailbox_spec.rb +34 -0
- data/spec/deprecate/future_spec.rb +32 -0
- data/spec/deprecate/internal_pool_spec.rb +4 -0
- data/spec/shared/actor_examples.rb +1259 -0
- data/spec/shared/group_examples.rb +121 -0
- data/spec/shared/mailbox_examples.rb +87 -0
- data/{lib/celluloid/rspec → spec/shared}/task_examples.rb +9 -8
- data/spec/spec_helper.rb +5 -42
- data/spec/support/configure_rspec.rb +77 -0
- data/spec/support/coverage.rb +4 -0
- data/spec/support/crash_checking.rb +68 -0
- data/spec/support/debugging.rb +31 -0
- data/spec/support/env.rb +21 -0
- data/{lib/celluloid/rspec/example_actor_class.rb → spec/support/examples/actor_class.rb} +21 -2
- data/spec/support/examples/call_class.rb +37 -0
- data/spec/support/examples/evented_mailbox_class.rb +27 -0
- data/spec/support/includer.rb +6 -0
- data/spec/support/logging.rb +55 -0
- data/spec/support/loose_threads.rb +68 -0
- data/spec/support/reset_class_variables.rb +27 -0
- data/spec/support/sleep_and_wait.rb +14 -0
- data/spec/support/stubbing.rb +14 -0
- metadata +276 -78
- data/lib/celluloid/actor_system.rb +0 -107
- data/lib/celluloid/call_chain.rb +0 -13
- data/lib/celluloid/cpu_counter.rb +0 -34
- data/lib/celluloid/evented_mailbox.rb +0 -73
- data/lib/celluloid/fsm.rb +0 -186
- data/lib/celluloid/handlers.rb +0 -41
- data/lib/celluloid/internal_pool.rb +0 -159
- data/lib/celluloid/legacy.rb +0 -9
- data/lib/celluloid/links.rb +0 -36
- data/lib/celluloid/logger.rb +0 -93
- data/lib/celluloid/logging/incident.rb +0 -21
- data/lib/celluloid/logging/incident_logger.rb +0 -129
- data/lib/celluloid/logging/incident_reporter.rb +0 -48
- data/lib/celluloid/logging/log_event.rb +0 -20
- data/lib/celluloid/logging/ring_buffer.rb +0 -65
- data/lib/celluloid/method.rb +0 -32
- data/lib/celluloid/notifications.rb +0 -83
- data/lib/celluloid/pool_manager.rb +0 -146
- data/lib/celluloid/probe.rb +0 -73
- data/lib/celluloid/properties.rb +0 -24
- data/lib/celluloid/proxies/abstract_proxy.rb +0 -20
- data/lib/celluloid/proxies/actor_proxy.rb +0 -38
- data/lib/celluloid/proxies/async_proxy.rb +0 -31
- data/lib/celluloid/proxies/block_proxy.rb +0 -29
- data/lib/celluloid/proxies/cell_proxy.rb +0 -68
- data/lib/celluloid/proxies/future_proxy.rb +0 -35
- data/lib/celluloid/proxies/sync_proxy.rb +0 -36
- data/lib/celluloid/receivers.rb +0 -63
- data/lib/celluloid/registry.rb +0 -57
- data/lib/celluloid/responses.rb +0 -44
- data/lib/celluloid/rspec/actor_examples.rb +0 -1054
- data/lib/celluloid/rspec/mailbox_examples.rb +0 -84
- data/lib/celluloid/signals.rb +0 -23
- data/lib/celluloid/stack_dump.rb +0 -133
- data/lib/celluloid/supervision_group.rb +0 -169
- data/lib/celluloid/supervisor.rb +0 -22
- data/lib/celluloid/task_set.rb +0 -49
- data/lib/celluloid/tasks/task_fiber.rb +0 -43
- data/lib/celluloid/tasks/task_thread.rb +0 -53
- data/lib/celluloid/thread_handle.rb +0 -50
- data/lib/celluloid/uuid.rb +0 -38
- data/spec/celluloid/actor_system_spec.rb +0 -69
- data/spec/celluloid/cpu_counter_spec.rb +0 -82
- data/spec/celluloid/fsm_spec.rb +0 -107
- data/spec/celluloid/internal_pool_spec.rb +0 -52
- data/spec/celluloid/links_spec.rb +0 -45
- data/spec/celluloid/logging/ring_buffer_spec.rb +0 -38
- data/spec/celluloid/notifications_spec.rb +0 -120
- data/spec/celluloid/pool_spec.rb +0 -92
- data/spec/celluloid/probe_spec.rb +0 -121
- data/spec/celluloid/properties_spec.rb +0 -42
- data/spec/celluloid/registry_spec.rb +0 -64
- data/spec/celluloid/stack_dump_spec.rb +0 -64
- data/spec/celluloid/supervision_group_spec.rb +0 -65
- data/spec/celluloid/supervisor_spec.rb +0 -103
- data/spec/celluloid/tasks/task_fiber_spec.rb +0 -5
- data/spec/celluloid/tasks/task_thread_spec.rb +0 -5
- data/spec/celluloid/thread_handle_spec.rb +0 -26
- data/spec/celluloid/uuid_spec.rb +0 -11
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
require 'logger'
|
|
2
|
-
module Celluloid
|
|
3
|
-
# A logger that holds all messages in circular buffers, then flushes the buffers
|
|
4
|
-
# when an event occurs at a configurable severity threshold.
|
|
5
|
-
#
|
|
6
|
-
# Unlike ruby's Logger, this class only supports a single progname.
|
|
7
|
-
class IncidentLogger
|
|
8
|
-
module Severity
|
|
9
|
-
include ::Logger::Severity
|
|
10
|
-
|
|
11
|
-
TRACE = -1
|
|
12
|
-
|
|
13
|
-
def severity_to_string(severity)
|
|
14
|
-
case severity
|
|
15
|
-
when TRACE then 'TRACE'
|
|
16
|
-
when DEBUG then 'DEBUG'
|
|
17
|
-
when INFO then 'INFO'
|
|
18
|
-
when WARN then 'WARN'
|
|
19
|
-
when ERROR then 'ERROR'
|
|
20
|
-
when FATAL then 'FATAL'
|
|
21
|
-
when UNKNOWN then 'UNKNOWN'
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
end
|
|
26
|
-
include Severity
|
|
27
|
-
|
|
28
|
-
# The progname (facility) for this instance.
|
|
29
|
-
attr_accessor :progname
|
|
30
|
-
|
|
31
|
-
# The logging level. Messages below this severity will not be logged at all.
|
|
32
|
-
attr_accessor :level
|
|
33
|
-
|
|
34
|
-
# The incident threshold. Messages at or above this severity will generate an
|
|
35
|
-
# incident and be published to incident reporters.
|
|
36
|
-
attr_accessor :threshold
|
|
37
|
-
|
|
38
|
-
# The buffer size limit. Each log level will retain this number of messages
|
|
39
|
-
# at maximum.
|
|
40
|
-
attr_accessor :sizelimit
|
|
41
|
-
|
|
42
|
-
attr_accessor :buffers
|
|
43
|
-
|
|
44
|
-
# Create a new IncidentLogger.
|
|
45
|
-
def initialize(progname=nil, options={})
|
|
46
|
-
@progname = progname || "default"
|
|
47
|
-
@level = options[:level] || DEBUG
|
|
48
|
-
@threshold = options[:threshold] || ERROR
|
|
49
|
-
@sizelimit = options[:sizelimit] || 100
|
|
50
|
-
|
|
51
|
-
@buffer_mutex = Mutex.new
|
|
52
|
-
@buffers = Hash.new do |progname_hash, _progname|
|
|
53
|
-
@buffer_mutex.synchronize do
|
|
54
|
-
progname_hash[_progname] = Hash.new do |severity_hash, severity|
|
|
55
|
-
severity_hash[severity] = RingBuffer.new(@sizelimit)
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
# When the IncidentLogger itself encounters an error, it falls back to logging to stderr
|
|
61
|
-
@fallback_logger = ::Logger.new(STDERR)
|
|
62
|
-
@fallback_logger.progname = "FALLBACK"
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
# add an event.
|
|
66
|
-
def add(severity, message=nil, progname=nil, &block)
|
|
67
|
-
progname ||= @progname
|
|
68
|
-
severity ||= UNKNOWN
|
|
69
|
-
|
|
70
|
-
if severity < @level
|
|
71
|
-
return event.id
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
if message.nil? && !block_given?
|
|
75
|
-
message = progname
|
|
76
|
-
progname = @progname
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
event = LogEvent.new(severity, message, progname, &block)
|
|
80
|
-
|
|
81
|
-
@buffers[progname][severity] << event
|
|
82
|
-
|
|
83
|
-
if severity >= @threshold
|
|
84
|
-
begin
|
|
85
|
-
Celluloid::Notifications.notifier.async.publish(incident_topic, create_incident(event))
|
|
86
|
-
rescue => ex
|
|
87
|
-
@fallback_logger.error(ex)
|
|
88
|
-
end
|
|
89
|
-
end
|
|
90
|
-
event.id
|
|
91
|
-
end
|
|
92
|
-
alias :log :add
|
|
93
|
-
|
|
94
|
-
# See docs for Logger#info
|
|
95
|
-
def trace (progname=nil, &block); add(TRACE, nil, progname, &block); end
|
|
96
|
-
def debug (progname=nil, &block); add(DEBUG, nil, progname, &block); end
|
|
97
|
-
def info (progname=nil, &block); add(INFO, nil, progname, &block); end
|
|
98
|
-
def warn (progname=nil, &block); add(WARN, nil, progname, &block); end
|
|
99
|
-
def error (progname=nil, &block); add(ERROR, nil, progname, &block); end
|
|
100
|
-
def fatal (progname=nil, &block); add(FATAL, nil, progname, &block); end
|
|
101
|
-
def unknown (progname=nil, &block); add(UNKNOWN, nil, progname, &block); end
|
|
102
|
-
|
|
103
|
-
def flush
|
|
104
|
-
messages = []
|
|
105
|
-
@buffer_mutex.synchronize do
|
|
106
|
-
@buffers.each do |progname, severities|
|
|
107
|
-
severities.each do |severity, buffer|
|
|
108
|
-
messages += buffer.flush
|
|
109
|
-
end
|
|
110
|
-
end
|
|
111
|
-
end
|
|
112
|
-
messages.sort
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
def clear
|
|
116
|
-
@buffer_mutex.synchronize do
|
|
117
|
-
@buffers.each { |buffer| buffer.clear }
|
|
118
|
-
end
|
|
119
|
-
end
|
|
120
|
-
|
|
121
|
-
def create_incident(event=nil)
|
|
122
|
-
Incident.new(flush, event)
|
|
123
|
-
end
|
|
124
|
-
|
|
125
|
-
def incident_topic
|
|
126
|
-
"log.incident.#{@progname}"
|
|
127
|
-
end
|
|
128
|
-
end
|
|
129
|
-
end
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
require 'logger'
|
|
2
|
-
module Celluloid
|
|
3
|
-
# Subscribes to log incident topics to report on them.
|
|
4
|
-
class IncidentReporter
|
|
5
|
-
include Celluloid
|
|
6
|
-
include Celluloid::Notifications
|
|
7
|
-
|
|
8
|
-
# get the time from the event
|
|
9
|
-
class Formatter < ::Logger::Formatter
|
|
10
|
-
def call(severity, time, progname, msg)
|
|
11
|
-
super(severity, msg.time, progname, msg.message)
|
|
12
|
-
end
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def initialize(*args)
|
|
16
|
-
subscribe(/log\.incident/, :report)
|
|
17
|
-
@logger = ::Logger.new(*args)
|
|
18
|
-
@logger.formatter = Formatter.new
|
|
19
|
-
@silenced = false
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def report(topic, incident)
|
|
23
|
-
return if @silenced
|
|
24
|
-
|
|
25
|
-
header = "INCIDENT"
|
|
26
|
-
header << " AT #{incident.triggering_event.time}" if incident.triggering_event
|
|
27
|
-
@logger << header
|
|
28
|
-
@logger << "\n"
|
|
29
|
-
@logger << "====================\n"
|
|
30
|
-
incident.events.each do |event|
|
|
31
|
-
@logger.add(event.severity, event, event.progname)
|
|
32
|
-
end
|
|
33
|
-
@logger << "====================\n"
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
def silence
|
|
37
|
-
@silenced = true
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def unsilence
|
|
41
|
-
@silenced = false
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
def silenced?
|
|
45
|
-
@silenced
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
end
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
module Celluloid
|
|
2
|
-
# Wraps a single log event.
|
|
3
|
-
class LogEvent
|
|
4
|
-
attr_accessor :id, :severity, :message, :progname, :time
|
|
5
|
-
|
|
6
|
-
def initialize(severity, message, progname, time=Time.now, &block)
|
|
7
|
-
# This id should be ordered. For now relies on Celluloid::UUID to be ordered.
|
|
8
|
-
# May want to use a generation/counter strategy for independence of uuid.
|
|
9
|
-
@id = Celluloid::UUID.generate
|
|
10
|
-
@severity = severity
|
|
11
|
-
@message = block_given? ? yield : message
|
|
12
|
-
@progname = progname
|
|
13
|
-
@time = time
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def <=>(other)
|
|
17
|
-
@id <=> other.id
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
end
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
module Celluloid
|
|
2
|
-
class RingBuffer
|
|
3
|
-
def initialize(size)
|
|
4
|
-
@size = size
|
|
5
|
-
@start = 0
|
|
6
|
-
@count = 0
|
|
7
|
-
@buffer = Array.new(size)
|
|
8
|
-
@mutex = Mutex.new
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
def full?
|
|
12
|
-
@count == @size
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def empty?
|
|
16
|
-
@count == 0
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def push(value)
|
|
20
|
-
@mutex.synchronize do
|
|
21
|
-
stop = (@start + @count) % @size
|
|
22
|
-
@buffer[stop] = value
|
|
23
|
-
if full?
|
|
24
|
-
@start = (@start + 1) % @size
|
|
25
|
-
else
|
|
26
|
-
@count += 1
|
|
27
|
-
end
|
|
28
|
-
value
|
|
29
|
-
end
|
|
30
|
-
end
|
|
31
|
-
alias :<< :push
|
|
32
|
-
|
|
33
|
-
def shift
|
|
34
|
-
@mutex.synchronize do
|
|
35
|
-
remove_element
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
def flush
|
|
40
|
-
values = []
|
|
41
|
-
@mutex.synchronize do
|
|
42
|
-
while !empty?
|
|
43
|
-
values << remove_element
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
values
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
def clear
|
|
50
|
-
@buffer = Array.new(@size)
|
|
51
|
-
@start = 0
|
|
52
|
-
@count = 0
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
private
|
|
56
|
-
|
|
57
|
-
def remove_element
|
|
58
|
-
return nil if empty?
|
|
59
|
-
value, @buffer[@start] = @buffer[@start], nil
|
|
60
|
-
@start = (@start + 1) % @size
|
|
61
|
-
@count -= 1
|
|
62
|
-
value
|
|
63
|
-
end
|
|
64
|
-
end
|
|
65
|
-
end
|
data/lib/celluloid/method.rb
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
module Celluloid
|
|
2
|
-
# Method handles that route through an actor proxy
|
|
3
|
-
class Method
|
|
4
|
-
|
|
5
|
-
def initialize(proxy, name)
|
|
6
|
-
raise NameError, "undefined method `#{name}'" unless proxy.respond_to? name
|
|
7
|
-
|
|
8
|
-
@proxy, @name = proxy, name
|
|
9
|
-
@klass = @proxy.class
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
def arity
|
|
13
|
-
@proxy.method_missing(:method, @name).arity
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def name
|
|
17
|
-
@proxy.method_missing(:method, @name).name
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def parameters
|
|
21
|
-
@proxy.method_missing(:method, @name).parameters
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
def call(*args, &block)
|
|
25
|
-
@proxy.__send__(@name, *args, &block)
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
def inspect
|
|
29
|
-
"#<Celluloid::Method #{@klass}##{@name}>"
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
end
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
module Celluloid
|
|
2
|
-
module Notifications
|
|
3
|
-
def self.notifier
|
|
4
|
-
Actor[:notifications_fanout] or raise DeadActorError, "notifications fanout actor not running"
|
|
5
|
-
end
|
|
6
|
-
|
|
7
|
-
def publish(pattern, *args)
|
|
8
|
-
Celluloid::Notifications.notifier.publish(pattern, *args)
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
def subscribe(pattern, method)
|
|
12
|
-
Celluloid::Notifications.notifier.subscribe(Actor.current, pattern, method)
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def unsubscribe(*args)
|
|
16
|
-
Celluloid::Notifications.notifier.unsubscribe(*args)
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
class Fanout
|
|
20
|
-
include Celluloid
|
|
21
|
-
trap_exit :prune
|
|
22
|
-
|
|
23
|
-
def initialize
|
|
24
|
-
@subscribers = []
|
|
25
|
-
@listeners_for = {}
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
def subscribe(actor, pattern, method)
|
|
29
|
-
subscriber = Subscriber.new(actor, pattern, method).tap do |s|
|
|
30
|
-
@subscribers << s
|
|
31
|
-
end
|
|
32
|
-
link actor
|
|
33
|
-
@listeners_for.clear
|
|
34
|
-
subscriber
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
def unsubscribe(subscriber)
|
|
38
|
-
@subscribers.reject! { |s| s.matches?(subscriber) }
|
|
39
|
-
@listeners_for.clear
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
def publish(pattern, *args)
|
|
43
|
-
listeners_for(pattern).each { |s| s.publish(pattern, *args) }
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
def listeners_for(pattern)
|
|
47
|
-
@listeners_for[pattern] ||= @subscribers.select { |s| s.subscribed_to?(pattern) }
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
def listening?(pattern)
|
|
51
|
-
listeners_for(pattern).any?
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
def prune(actor, reason=nil)
|
|
55
|
-
@subscribers.reject! { |s| s.actor == actor }
|
|
56
|
-
@listeners_for.clear
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
class Subscriber
|
|
61
|
-
attr_accessor :actor, :pattern, :method
|
|
62
|
-
|
|
63
|
-
def initialize(actor, pattern, method)
|
|
64
|
-
@actor = actor
|
|
65
|
-
@pattern = pattern
|
|
66
|
-
@method = method
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
def publish(pattern, *args)
|
|
70
|
-
actor.async method, pattern, *args
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
def subscribed_to?(pattern)
|
|
74
|
-
!pattern || @pattern === pattern.to_s
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
def matches?(subscriber_or_pattern)
|
|
78
|
-
self === subscriber_or_pattern ||
|
|
79
|
-
@pattern && @pattern === subscriber_or_pattern
|
|
80
|
-
end
|
|
81
|
-
end
|
|
82
|
-
end
|
|
83
|
-
end
|
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
require 'set'
|
|
2
|
-
|
|
3
|
-
module Celluloid
|
|
4
|
-
# Manages a fixed-size pool of workers
|
|
5
|
-
# Delegates work (i.e. methods) and supervises workers
|
|
6
|
-
# Don't use this class directly. Instead use MyKlass.pool
|
|
7
|
-
class PoolManager
|
|
8
|
-
include Celluloid
|
|
9
|
-
trap_exit :__crash_handler__
|
|
10
|
-
finalizer :__shutdown__
|
|
11
|
-
|
|
12
|
-
def initialize(worker_class, options = {})
|
|
13
|
-
@size = options[:size] || [Celluloid.cores || 2, 2].max
|
|
14
|
-
raise ArgumentError, "minimum pool size is 2" if @size < 2
|
|
15
|
-
|
|
16
|
-
@worker_class = worker_class
|
|
17
|
-
@args = options[:args] ? Array(options[:args]) : []
|
|
18
|
-
|
|
19
|
-
@idle = @size.times.map { worker_class.new_link(*@args) }
|
|
20
|
-
|
|
21
|
-
# FIXME: Another data structure (e.g. Set) would be more appropriate
|
|
22
|
-
# here except it causes MRI to crash :o
|
|
23
|
-
@busy = []
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
def __shutdown__
|
|
27
|
-
terminators = (@idle + @busy).map do |actor|
|
|
28
|
-
begin
|
|
29
|
-
actor.future(:terminate)
|
|
30
|
-
rescue DeadActorError
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
terminators.compact.each { |terminator| terminator.value rescue nil }
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
def _send_(method, *args, &block)
|
|
38
|
-
worker = __provision_worker__
|
|
39
|
-
|
|
40
|
-
begin
|
|
41
|
-
worker._send_ method, *args, &block
|
|
42
|
-
rescue DeadActorError # if we get a dead actor out of the pool
|
|
43
|
-
wait :respawn_complete
|
|
44
|
-
worker = __provision_worker__
|
|
45
|
-
retry
|
|
46
|
-
rescue Exception => ex
|
|
47
|
-
abort ex
|
|
48
|
-
ensure
|
|
49
|
-
if worker.alive?
|
|
50
|
-
@idle << worker
|
|
51
|
-
@busy.delete worker
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
def name
|
|
57
|
-
_send_ @mailbox, :name
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
def is_a?(klass)
|
|
61
|
-
_send_ :is_a?, klass
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
def kind_of?(klass)
|
|
65
|
-
_send_ :kind_of?, klass
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
def methods(include_ancestors = true)
|
|
69
|
-
_send_ :methods, include_ancestors
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
def to_s
|
|
73
|
-
_send_ :to_s
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
def inspect
|
|
77
|
-
_send_ :inspect
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
def size
|
|
81
|
-
@size
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
def size=(new_size)
|
|
85
|
-
new_size = [0, new_size].max
|
|
86
|
-
|
|
87
|
-
if new_size > size
|
|
88
|
-
delta = new_size - size
|
|
89
|
-
delta.times { @idle << @worker_class.new_link(*@args) }
|
|
90
|
-
else
|
|
91
|
-
(size - new_size).times do
|
|
92
|
-
worker = __provision_worker__
|
|
93
|
-
unlink worker
|
|
94
|
-
@busy.delete worker
|
|
95
|
-
worker.terminate
|
|
96
|
-
end
|
|
97
|
-
end
|
|
98
|
-
@size = new_size
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
def busy_size
|
|
102
|
-
@busy.length
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
def idle_size
|
|
106
|
-
@idle.length
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
# Provision a new worker
|
|
110
|
-
def __provision_worker__
|
|
111
|
-
Task.current.guard_warnings = true
|
|
112
|
-
while @idle.empty?
|
|
113
|
-
# Wait for responses from one of the busy workers
|
|
114
|
-
response = exclusive { receive { |msg| msg.is_a?(Response) } }
|
|
115
|
-
Thread.current[:celluloid_actor].handle_message(response)
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
worker = @idle.shift
|
|
119
|
-
@busy << worker
|
|
120
|
-
|
|
121
|
-
worker
|
|
122
|
-
end
|
|
123
|
-
|
|
124
|
-
# Spawn a new worker for every crashed one
|
|
125
|
-
def __crash_handler__(actor, reason)
|
|
126
|
-
@busy.delete actor
|
|
127
|
-
@idle.delete actor
|
|
128
|
-
return unless reason
|
|
129
|
-
|
|
130
|
-
@idle << @worker_class.new_link(*@args)
|
|
131
|
-
signal :respawn_complete
|
|
132
|
-
end
|
|
133
|
-
|
|
134
|
-
def respond_to?(method, include_private = false)
|
|
135
|
-
super || @worker_class.instance_methods.include?(method.to_sym)
|
|
136
|
-
end
|
|
137
|
-
|
|
138
|
-
def method_missing(method, *args, &block)
|
|
139
|
-
if respond_to?(method)
|
|
140
|
-
_send_ method, *args, &block
|
|
141
|
-
else
|
|
142
|
-
super
|
|
143
|
-
end
|
|
144
|
-
end
|
|
145
|
-
end
|
|
146
|
-
end
|
data/lib/celluloid/probe.rb
DELETED
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
require 'celluloid'
|
|
2
|
-
|
|
3
|
-
$CELLULOID_MONITORING = true
|
|
4
|
-
|
|
5
|
-
module Celluloid
|
|
6
|
-
class Probe
|
|
7
|
-
include Celluloid
|
|
8
|
-
include Celluloid::Notifications
|
|
9
|
-
|
|
10
|
-
NOTIFICATIONS_TOPIC_BASE = 'celluloid.events.%s'
|
|
11
|
-
INITIAL_EVENTS = Queue.new
|
|
12
|
-
|
|
13
|
-
class << self
|
|
14
|
-
def run
|
|
15
|
-
# spawn the actor if not found
|
|
16
|
-
supervise_as(:probe_actor) unless Actor[:probe_actor] && Actor[:probe_actor].alive?
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def actor_created(actor)
|
|
20
|
-
trigger_event(:actor_created, actor)
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def actor_named(actor)
|
|
24
|
-
trigger_event(:actor_named, actor)
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
def actor_died(actor)
|
|
28
|
-
trigger_event(:actor_died, actor)
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
def actors_linked(a, b)
|
|
32
|
-
a = find_actor(a)
|
|
33
|
-
b = find_actor(b)
|
|
34
|
-
trigger_event(:actors_linked, a, b)
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
private
|
|
38
|
-
|
|
39
|
-
def trigger_event(name, *args)
|
|
40
|
-
return unless $CELLULOID_MONITORING
|
|
41
|
-
probe_actor = Actor[:probe_actor]
|
|
42
|
-
if probe_actor
|
|
43
|
-
probe_actor.async.dispatch_event(name, args)
|
|
44
|
-
else
|
|
45
|
-
INITIAL_EVENTS << [name, args]
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
def find_actor(obj)
|
|
50
|
-
if obj.__send__(:class) == Actor
|
|
51
|
-
obj
|
|
52
|
-
elsif owner = obj.instance_variable_get(OWNER_IVAR)
|
|
53
|
-
owner
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
def initialize
|
|
59
|
-
async.first_run
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
def first_run
|
|
63
|
-
until INITIAL_EVENTS.size == 0
|
|
64
|
-
event = INITIAL_EVENTS.pop
|
|
65
|
-
dispatch_event(*event)
|
|
66
|
-
end
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
def dispatch_event(cmd, args)
|
|
70
|
-
publish(NOTIFICATIONS_TOPIC_BASE % cmd, args)
|
|
71
|
-
end
|
|
72
|
-
end
|
|
73
|
-
end
|
data/lib/celluloid/properties.rb
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
module Celluloid
|
|
2
|
-
# Properties define inheritable attributes of classes, somewhat similar to
|
|
3
|
-
# Rails cattr_*/mattr_* or class_attribute
|
|
4
|
-
module Properties
|
|
5
|
-
def property(name, opts = {})
|
|
6
|
-
default = opts.fetch(:default, nil)
|
|
7
|
-
multi = opts.fetch(:multi, false)
|
|
8
|
-
ivar_name = "@#{name}".to_sym
|
|
9
|
-
|
|
10
|
-
ancestors.first.send(:define_singleton_method, name) do |value = nil, *extra|
|
|
11
|
-
if value
|
|
12
|
-
value = value ? [value, *send(name), *extra].uniq : [] if multi
|
|
13
|
-
instance_variable_set(ivar_name, value)
|
|
14
|
-
elsif instance_variables.include?(ivar_name)
|
|
15
|
-
instance_variable_get(ivar_name)
|
|
16
|
-
elsif superclass.respond_to? name
|
|
17
|
-
superclass.send(name)
|
|
18
|
-
else
|
|
19
|
-
default
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
end
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
module Celluloid
|
|
2
|
-
# Base class of all Celluloid proxies
|
|
3
|
-
class AbstractProxy < BasicObject
|
|
4
|
-
# Used for reflecting on proxy objects themselves
|
|
5
|
-
def __class__; AbstractProxy; end
|
|
6
|
-
|
|
7
|
-
# Needed for storing proxies in data structures
|
|
8
|
-
needed = [:object_id, :__id__, :hash] - instance_methods
|
|
9
|
-
if needed.any?
|
|
10
|
-
include ::Kernel.dup.module_eval {
|
|
11
|
-
undef_method(*(instance_methods - needed))
|
|
12
|
-
self
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
# rubinius bug? These methods disappear when we include hacked kernel
|
|
16
|
-
define_method :==, ::BasicObject.instance_method(:==) unless instance_methods.include?(:==)
|
|
17
|
-
alias_method(:equal?, :==) unless instance_methods.include?(:equal?)
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
end
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
module Celluloid
|
|
2
|
-
# A proxy which controls the Actor lifecycle
|
|
3
|
-
class ActorProxy < AbstractProxy
|
|
4
|
-
attr_reader :thread, :mailbox
|
|
5
|
-
|
|
6
|
-
# Used for reflecting on proxy objects themselves
|
|
7
|
-
def __class__; ActorProxy; end
|
|
8
|
-
|
|
9
|
-
def initialize(thread, mailbox)
|
|
10
|
-
@thread = thread
|
|
11
|
-
@mailbox = mailbox
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def inspect
|
|
15
|
-
# TODO: use a system event to fetch actor state: tasks?
|
|
16
|
-
"#<Celluloid::ActorProxy(#{@mailbox.address}) alive>"
|
|
17
|
-
rescue DeadActorError
|
|
18
|
-
"#<Celluloid::ActorProxy(#{@mailbox.address}) dead>"
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def alive?
|
|
22
|
-
@mailbox.alive?
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
# Terminate the associated actor
|
|
26
|
-
def terminate
|
|
27
|
-
terminate!
|
|
28
|
-
Actor.join(self)
|
|
29
|
-
nil
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
# Terminate the associated actor asynchronously
|
|
33
|
-
def terminate!
|
|
34
|
-
::Kernel.raise DeadActorError, "actor already terminated" unless alive?
|
|
35
|
-
@mailbox << TerminationRequest.new
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
end
|