engineyard-serverside 1.5.23.ruby19.8 → 1.5.23.ruby19.9
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/engineyard-serverside.rb +3 -1
- data/lib/engineyard-serverside/cli.rb +11 -19
- data/lib/engineyard-serverside/deploy.rb +3 -3
- data/lib/engineyard-serverside/future.rb +33 -0
- data/lib/engineyard-serverside/futures/celluloid.rb +25 -0
- data/lib/engineyard-serverside/futures/dataflow.rb +25 -0
- data/lib/engineyard-serverside/logged_output.rb +8 -3
- data/lib/engineyard-serverside/task.rb +9 -12
- data/lib/engineyard-serverside/version.rb +1 -1
- data/lib/vendor/celluloid/lib/celluloid.rb +261 -0
- data/lib/vendor/celluloid/lib/celluloid/actor.rb +242 -0
- data/lib/vendor/celluloid/lib/celluloid/actor_pool.rb +54 -0
- data/lib/vendor/celluloid/lib/celluloid/actor_proxy.rb +75 -0
- data/lib/vendor/celluloid/lib/celluloid/application.rb +78 -0
- data/lib/vendor/celluloid/lib/celluloid/calls.rb +94 -0
- data/lib/vendor/celluloid/lib/celluloid/core_ext.rb +14 -0
- data/lib/vendor/celluloid/lib/celluloid/events.rb +14 -0
- data/lib/vendor/celluloid/lib/celluloid/fiber.rb +33 -0
- data/lib/vendor/celluloid/lib/celluloid/fsm.rb +141 -0
- data/lib/vendor/celluloid/lib/celluloid/future.rb +60 -0
- data/lib/vendor/celluloid/lib/celluloid/links.rb +61 -0
- data/lib/vendor/celluloid/lib/celluloid/logger.rb +32 -0
- data/lib/vendor/celluloid/lib/celluloid/mailbox.rb +124 -0
- data/lib/vendor/celluloid/lib/celluloid/receivers.rb +66 -0
- data/lib/vendor/celluloid/lib/celluloid/registry.rb +33 -0
- data/lib/vendor/celluloid/lib/celluloid/responses.rb +26 -0
- data/lib/vendor/celluloid/lib/celluloid/rspec.rb +2 -0
- data/lib/vendor/celluloid/lib/celluloid/signals.rb +50 -0
- data/lib/vendor/celluloid/lib/celluloid/supervisor.rb +57 -0
- data/lib/vendor/celluloid/lib/celluloid/task.rb +73 -0
- data/lib/vendor/celluloid/lib/celluloid/tcp_server.rb +33 -0
- data/lib/vendor/celluloid/lib/celluloid/timers.rb +109 -0
- data/lib/vendor/celluloid/lib/celluloid/version.rb +4 -0
- data/lib/vendor/dataflow/dataflow.rb +124 -0
- data/lib/vendor/dataflow/dataflow/actor.rb +22 -0
- data/lib/vendor/dataflow/dataflow/equality.rb +44 -0
- data/lib/vendor/dataflow/dataflow/future_queue.rb +24 -0
- data/lib/vendor/dataflow/dataflow/port.rb +54 -0
- data/lib/vendor/open4/lib/open4.rb +432 -0
- data/lib/vendor/thor/lib/thor.rb +244 -0
- data/lib/vendor/thor/lib/thor/actions.rb +275 -0
- data/lib/vendor/thor/lib/thor/actions/create_file.rb +103 -0
- data/lib/vendor/thor/lib/thor/actions/directory.rb +91 -0
- data/lib/vendor/thor/lib/thor/actions/empty_directory.rb +134 -0
- data/lib/vendor/thor/lib/thor/actions/file_manipulation.rb +223 -0
- data/lib/vendor/thor/lib/thor/actions/inject_into_file.rb +104 -0
- data/lib/vendor/thor/lib/thor/base.rb +540 -0
- data/lib/vendor/thor/lib/thor/core_ext/file_binary_read.rb +9 -0
- data/lib/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb +75 -0
- data/lib/vendor/thor/lib/thor/core_ext/ordered_hash.rb +100 -0
- data/lib/vendor/thor/lib/thor/error.rb +30 -0
- data/lib/vendor/thor/lib/thor/group.rb +271 -0
- data/lib/vendor/thor/lib/thor/invocation.rb +180 -0
- data/lib/vendor/thor/lib/thor/parser.rb +4 -0
- data/lib/vendor/thor/lib/thor/parser/argument.rb +67 -0
- data/lib/vendor/thor/lib/thor/parser/arguments.rb +150 -0
- data/lib/vendor/thor/lib/thor/parser/option.rb +128 -0
- data/lib/vendor/thor/lib/thor/parser/options.rb +169 -0
- data/lib/vendor/thor/lib/thor/rake_compat.rb +66 -0
- data/lib/vendor/thor/lib/thor/runner.rb +314 -0
- data/lib/vendor/thor/lib/thor/shell.rb +83 -0
- data/lib/vendor/thor/lib/thor/shell/basic.rb +239 -0
- data/lib/vendor/thor/lib/thor/shell/color.rb +108 -0
- data/lib/vendor/thor/lib/thor/task.rb +102 -0
- data/lib/vendor/thor/lib/thor/util.rb +230 -0
- data/lib/vendor/thor/lib/thor/version.rb +3 -0
- metadata +70 -10
@@ -0,0 +1,124 @@
|
|
1
|
+
require 'thread'
|
2
|
+
|
3
|
+
module Celluloid
|
4
|
+
class MailboxError < StandardError; end # you can't message the dead
|
5
|
+
class MailboxShutdown < StandardError; end # raised if the mailbox can no longer be used
|
6
|
+
|
7
|
+
# Actors communicate with asynchronous messages. Messages are buffered in
|
8
|
+
# Mailboxes until Actors can act upon them.
|
9
|
+
class Mailbox
|
10
|
+
include Enumerable
|
11
|
+
|
12
|
+
# A unique address at which this mailbox can be found
|
13
|
+
alias_method :address, :object_id
|
14
|
+
|
15
|
+
def initialize
|
16
|
+
@messages = []
|
17
|
+
@lock = Mutex.new
|
18
|
+
@dead = false
|
19
|
+
@condition = ConditionVariable.new
|
20
|
+
end
|
21
|
+
|
22
|
+
# Add a message to the Mailbox
|
23
|
+
def <<(message)
|
24
|
+
@lock.synchronize do
|
25
|
+
raise MailboxError, "dead recipient" if @dead
|
26
|
+
|
27
|
+
@messages << message
|
28
|
+
@condition.signal
|
29
|
+
end
|
30
|
+
nil
|
31
|
+
end
|
32
|
+
|
33
|
+
# Add a high-priority system event to the Mailbox
|
34
|
+
def system_event(event)
|
35
|
+
@lock.synchronize do
|
36
|
+
unless @dead # Silently fail if messages are sent to dead actors
|
37
|
+
@messages.unshift event
|
38
|
+
@condition.signal
|
39
|
+
end
|
40
|
+
end
|
41
|
+
nil
|
42
|
+
end
|
43
|
+
|
44
|
+
# Receive a message from the Mailbox
|
45
|
+
def receive(timeout = nil, &block)
|
46
|
+
message = nil
|
47
|
+
|
48
|
+
@lock.synchronize do
|
49
|
+
raise MailboxError, "attempted to receive from a dead mailbox" if @dead
|
50
|
+
|
51
|
+
begin
|
52
|
+
message = next_message(&block)
|
53
|
+
|
54
|
+
unless message
|
55
|
+
if timeout
|
56
|
+
now = Time.now
|
57
|
+
wait_until ||= now + timeout
|
58
|
+
wait_interval = wait_until - now
|
59
|
+
return if wait_interval < 0
|
60
|
+
else
|
61
|
+
wait_interval = nil
|
62
|
+
end
|
63
|
+
|
64
|
+
@condition.wait(@lock, wait_interval)
|
65
|
+
end
|
66
|
+
end until message
|
67
|
+
end
|
68
|
+
|
69
|
+
message
|
70
|
+
end
|
71
|
+
|
72
|
+
# Retrieve the next message in the mailbox
|
73
|
+
def next_message
|
74
|
+
message = nil
|
75
|
+
|
76
|
+
if block_given?
|
77
|
+
index = @messages.index do |msg|
|
78
|
+
yield(msg) || msg.is_a?(SystemEvent)
|
79
|
+
end
|
80
|
+
|
81
|
+
message = @messages.slice!(index, 1).first if index
|
82
|
+
else
|
83
|
+
message = @messages.shift
|
84
|
+
end
|
85
|
+
|
86
|
+
raise message if message.is_a? SystemEvent
|
87
|
+
message
|
88
|
+
end
|
89
|
+
|
90
|
+
# Shut down this mailbox and clean up its contents
|
91
|
+
def shutdown
|
92
|
+
messages = nil
|
93
|
+
|
94
|
+
@lock.synchronize do
|
95
|
+
messages = @messages
|
96
|
+
@messages = []
|
97
|
+
@dead = true
|
98
|
+
end
|
99
|
+
|
100
|
+
messages.each { |msg| msg.cleanup if msg.respond_to? :cleanup }
|
101
|
+
true
|
102
|
+
end
|
103
|
+
|
104
|
+
# Is the mailbox alive?
|
105
|
+
def alive?
|
106
|
+
!@dead
|
107
|
+
end
|
108
|
+
|
109
|
+
# Cast to an array
|
110
|
+
def to_a
|
111
|
+
@lock.synchronize { @messages.dup }
|
112
|
+
end
|
113
|
+
|
114
|
+
# Iterate through the mailbox
|
115
|
+
def each(&block)
|
116
|
+
to_a.each(&block)
|
117
|
+
end
|
118
|
+
|
119
|
+
# Inspect the contents of the Mailbox
|
120
|
+
def inspect
|
121
|
+
"#<#{self.class}:#{object_id.to_s(16)} @messages=[#{map { |m| m.inspect }.join(', ')}]>"
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
module Celluloid
|
4
|
+
# Allow methods to directly interact with the actor protocol
|
5
|
+
class Receivers
|
6
|
+
def initialize
|
7
|
+
@receivers = Set.new
|
8
|
+
@timers = Timers.new
|
9
|
+
end
|
10
|
+
|
11
|
+
# Receive an asynchronous message
|
12
|
+
def receive(timeout = nil, &block)
|
13
|
+
receiver = Receiver.new block
|
14
|
+
|
15
|
+
if timeout
|
16
|
+
receiver.timer = @timers.add(timeout) do
|
17
|
+
@receivers.delete receiver
|
18
|
+
receiver.resume
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
@receivers << receiver
|
23
|
+
Task.suspend
|
24
|
+
end
|
25
|
+
|
26
|
+
# How long to wait until the next timer fires
|
27
|
+
def wait_interval
|
28
|
+
@timers.wait_interval
|
29
|
+
end
|
30
|
+
|
31
|
+
# Fire any pending timers
|
32
|
+
def fire_timers
|
33
|
+
@timers.fire
|
34
|
+
end
|
35
|
+
|
36
|
+
# Handle incoming messages
|
37
|
+
def handle_message(message)
|
38
|
+
receiver = @receivers.find { |r| r.match(message) }
|
39
|
+
return unless receiver
|
40
|
+
|
41
|
+
@receivers.delete receiver
|
42
|
+
@timers.cancel receiver.timer if receiver.timer
|
43
|
+
receiver.resume message
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# Methods blocking on a call to receive
|
48
|
+
class Receiver
|
49
|
+
attr_accessor :timer
|
50
|
+
|
51
|
+
def initialize(block)
|
52
|
+
@block = block
|
53
|
+
@task = Task.current
|
54
|
+
@timer = nil
|
55
|
+
end
|
56
|
+
|
57
|
+
# Match a message with this receiver's block
|
58
|
+
def match(message)
|
59
|
+
@block.call(message) if @block
|
60
|
+
end
|
61
|
+
|
62
|
+
def resume(message = nil)
|
63
|
+
@task.resume message
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'thread'
|
2
|
+
|
3
|
+
module Celluloid
|
4
|
+
# The Registry allows us to refer to specific actors by human-meaningful names
|
5
|
+
module Registry
|
6
|
+
@@registry = {}
|
7
|
+
@@registry_lock = Mutex.new
|
8
|
+
|
9
|
+
# Register an Actor
|
10
|
+
def []=(name, actor)
|
11
|
+
actor_singleton = class << actor; self; end
|
12
|
+
unless actor_singleton.ancestors.include? ActorProxy
|
13
|
+
raise TypeError, "not an actor"
|
14
|
+
end
|
15
|
+
|
16
|
+
@@registry_lock.synchronize do
|
17
|
+
@@registry[name.to_sym] = actor
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# Retrieve an actor by name
|
22
|
+
def [](name)
|
23
|
+
@@registry_lock.synchronize do
|
24
|
+
@@registry[name.to_sym]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# List all registered actors by name
|
29
|
+
def registered
|
30
|
+
@@registry_lock.synchronize { @@registry.keys }
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Celluloid
|
2
|
+
# Responses to calls
|
3
|
+
class Response
|
4
|
+
attr_reader :call_id, :value
|
5
|
+
|
6
|
+
def initialize(call_id, value)
|
7
|
+
@call_id, @value = call_id, value
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
# Call completed successfully
|
12
|
+
class SuccessResponse < Response; end
|
13
|
+
|
14
|
+
# Call was aborted due to caller error
|
15
|
+
class ErrorResponse < Response
|
16
|
+
def value
|
17
|
+
if super.is_a? AbortError
|
18
|
+
# Aborts are caused by caller error, so ensure they capture the
|
19
|
+
# caller's backtrace instead of the receiver's
|
20
|
+
raise super.cause.class.new(super.cause.message)
|
21
|
+
else
|
22
|
+
raise super
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Celluloid
|
2
|
+
# Event signaling between methods of the same object
|
3
|
+
class Signals
|
4
|
+
attr_reader :waiting
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@waiting = {}
|
8
|
+
end
|
9
|
+
|
10
|
+
# Wait for the given signal and return the associated value
|
11
|
+
def wait(signal)
|
12
|
+
tasks = @waiting[signal]
|
13
|
+
|
14
|
+
case tasks
|
15
|
+
when Array
|
16
|
+
tasks << Task.current
|
17
|
+
when NilClass
|
18
|
+
@waiting[signal] = Task.current
|
19
|
+
else
|
20
|
+
@waiting[signal] = [tasks, Task.current]
|
21
|
+
end
|
22
|
+
|
23
|
+
Task.suspend
|
24
|
+
end
|
25
|
+
|
26
|
+
# Send a signal to all method calls waiting for the given name
|
27
|
+
# Returns true if any calls were signaled, or false otherwise
|
28
|
+
def send(name, value = nil)
|
29
|
+
tasks = @waiting.delete name
|
30
|
+
|
31
|
+
case tasks
|
32
|
+
when Array
|
33
|
+
tasks.each { |task| run_task task, value }
|
34
|
+
when NilClass
|
35
|
+
Logger.debug("spurious signal: #{name}")
|
36
|
+
else
|
37
|
+
run_task tasks, value
|
38
|
+
end
|
39
|
+
|
40
|
+
value
|
41
|
+
end
|
42
|
+
|
43
|
+
# Run the given task, reporting errors that occur
|
44
|
+
def run_task(task, value)
|
45
|
+
task.resume(value)
|
46
|
+
rescue => ex
|
47
|
+
Celluloid::Logger.crash("signaling error", ex)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Celluloid
|
2
|
+
# Supervisors are actors that watch over other actors and restart them if
|
3
|
+
# they crash
|
4
|
+
class Supervisor
|
5
|
+
include Celluloid
|
6
|
+
trap_exit :restart_actor
|
7
|
+
|
8
|
+
# Retrieve the actor this supervisor is supervising
|
9
|
+
attr_reader :actor
|
10
|
+
|
11
|
+
def self.supervise(klass, *args, &block)
|
12
|
+
new(nil, klass, *args, &block)
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.supervise_as(name, klass, *args, &block)
|
16
|
+
new(name, klass, *args, &block)
|
17
|
+
end
|
18
|
+
|
19
|
+
def initialize(name, klass, *args, &block)
|
20
|
+
@name, @klass, @args, @block = name, klass, args, block
|
21
|
+
@started = false
|
22
|
+
|
23
|
+
start_actor
|
24
|
+
end
|
25
|
+
|
26
|
+
def start_actor(start_attempts = 3, sleep_interval = 30)
|
27
|
+
failures = 0
|
28
|
+
|
29
|
+
begin
|
30
|
+
@actor = @klass.new_link(*@args, &@block)
|
31
|
+
rescue => ex
|
32
|
+
failures += 1
|
33
|
+
if failures >= start_attempts
|
34
|
+
failures = 0
|
35
|
+
|
36
|
+
Logger.warn("#{@klass} is crashing on initialize too quickly, sleeping for #{sleep_interval} seconds")
|
37
|
+
sleep sleep_interval
|
38
|
+
end
|
39
|
+
retry
|
40
|
+
end
|
41
|
+
|
42
|
+
@started = true
|
43
|
+
Actor[@name] = @actor if @name
|
44
|
+
end
|
45
|
+
|
46
|
+
# When actors die, regardless of the reason, restart them
|
47
|
+
def restart_actor(actor, reason)
|
48
|
+
start_actor if @started
|
49
|
+
end
|
50
|
+
|
51
|
+
def inspect
|
52
|
+
str = "#<#{self.class}(#{@klass}):0x#{object_id.to_s(16)}"
|
53
|
+
str << " " << @args.map { |arg| arg.inspect }.join(' ') unless @args.empty?
|
54
|
+
str << ">"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module Celluloid
|
2
|
+
# Trying to resume a dead task
|
3
|
+
class DeadTaskError < StandardError; end
|
4
|
+
|
5
|
+
# Tasks are interruptable/resumable execution contexts used to run methods
|
6
|
+
class Task
|
7
|
+
class TerminatedError < StandardError; end # kill a running fiber
|
8
|
+
|
9
|
+
attr_reader :type # what type of task is this?
|
10
|
+
|
11
|
+
# Obtain the current task
|
12
|
+
def self.current
|
13
|
+
task = Fiber.current.task
|
14
|
+
raise "not in task scope" unless task
|
15
|
+
task
|
16
|
+
end
|
17
|
+
|
18
|
+
# Suspend the running task, deferring to the scheduler
|
19
|
+
def self.suspend(value = nil)
|
20
|
+
result = Fiber.yield(value)
|
21
|
+
raise TerminatedError, "task was terminated" if result == TerminatedError
|
22
|
+
result
|
23
|
+
end
|
24
|
+
|
25
|
+
# Run the given block within a task
|
26
|
+
def initialize(type)
|
27
|
+
@type = type
|
28
|
+
|
29
|
+
actor = Thread.current[:actor]
|
30
|
+
mailbox = Thread.current[:mailbox]
|
31
|
+
|
32
|
+
@fiber = Fiber.new do
|
33
|
+
Thread.current[:actor] = actor
|
34
|
+
Thread.current[:mailbox] = mailbox
|
35
|
+
|
36
|
+
Fiber.current.task = self
|
37
|
+
|
38
|
+
begin
|
39
|
+
yield
|
40
|
+
rescue TerminatedError
|
41
|
+
# Task was explicitly terminated
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# Resume a suspended task, giving it a value to return if needed
|
47
|
+
def resume(value = nil)
|
48
|
+
@fiber.resume value
|
49
|
+
nil
|
50
|
+
rescue FiberError
|
51
|
+
raise DeadTaskError, "cannot resume a dead task"
|
52
|
+
rescue RuntimeError => ex
|
53
|
+
# These occur spuriously on 1.9.3 if we shut down an actor with running tasks
|
54
|
+
return if ex.message == ""
|
55
|
+
raise
|
56
|
+
end
|
57
|
+
|
58
|
+
# Terminate this task
|
59
|
+
def terminate
|
60
|
+
resume TerminatedError
|
61
|
+
rescue FiberError
|
62
|
+
# If we're getting this the task should already be dead
|
63
|
+
end
|
64
|
+
|
65
|
+
# Is the current task still running?
|
66
|
+
def running?; @fiber.alive?; end
|
67
|
+
|
68
|
+
# Nicer string inspect for tasks
|
69
|
+
def inspect
|
70
|
+
"<Celluloid::Task:0x#{object_id.to_s(16)} @type=#{@type.inspect}, @running=#{@fiber.alive?}>"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'socket'
|
2
|
+
|
3
|
+
module Celluloid
|
4
|
+
# A TCPServer that runs as an actor
|
5
|
+
class TCPServer
|
6
|
+
include Celluloid::IO
|
7
|
+
|
8
|
+
# Bind a TCP server to the given host and port
|
9
|
+
def initialize(host, port)
|
10
|
+
@server = ::TCPServer.new host, port
|
11
|
+
run!
|
12
|
+
end
|
13
|
+
|
14
|
+
# Run the TCP server event loop
|
15
|
+
def run
|
16
|
+
while true
|
17
|
+
wait_readable(@server)
|
18
|
+
on_connect @server.accept
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# Terminate this server
|
23
|
+
def terminate
|
24
|
+
@server.close
|
25
|
+
super
|
26
|
+
end
|
27
|
+
|
28
|
+
# Called whenever a new connection is opened
|
29
|
+
def on_connect(connection)
|
30
|
+
connection.close
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|