engineyard-serverside 1.5.23.ruby19.8 → 1.5.23.ruby19.9
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.
- 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
|