engineyard-serverside 1.5.26 → 1.5.27.pre
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 +1 -2
- data/lib/engineyard-serverside/cli.rb +19 -35
- data/lib/engineyard-serverside/deploy.rb +4 -3
- data/lib/engineyard-serverside/future.rb +29 -0
- data/lib/engineyard-serverside/futures/celluloid.rb +25 -0
- data/lib/engineyard-serverside/futures/dataflow.rb +31 -0
- data/lib/engineyard-serverside/server.rb +27 -2
- data/lib/engineyard-serverside/task.rb +10 -11
- 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/spec/basic_deploy_spec.rb +1 -1
- data/spec/bundler_deploy_spec.rb +1 -1
- data/spec/nodejs_deploy_spec.rb +1 -1
- data/spec/rails31_deploy_spec.rb +1 -1
- data/spec/services_deploy_spec.rb +1 -1
- metadata +78 -87
@@ -11,11 +11,9 @@ $LOAD_PATH.unshift File.expand_path('vendor/thor/lib', File.dirname(__FILE__))
|
|
11
11
|
$LOAD_PATH.unshift File.expand_path('vendor/open4/lib', File.dirname(__FILE__))
|
12
12
|
$LOAD_PATH.unshift File.expand_path('vendor/escape/lib', File.dirname(__FILE__))
|
13
13
|
$LOAD_PATH.unshift File.expand_path('vendor/json_pure/lib', File.dirname(__FILE__))
|
14
|
-
$LOAD_PATH.unshift File.expand_path('vendor/dataflow', File.dirname(__FILE__))
|
15
14
|
|
16
15
|
require 'escape'
|
17
16
|
require 'json'
|
18
|
-
require 'dataflow'
|
19
17
|
|
20
18
|
require 'engineyard-serverside/version'
|
21
19
|
require 'engineyard-serverside/strategies/git'
|
@@ -27,6 +25,7 @@ require 'engineyard-serverside/lockfile_parser'
|
|
27
25
|
require 'engineyard-serverside/cli'
|
28
26
|
require 'engineyard-serverside/configuration'
|
29
27
|
require 'engineyard-serverside/deprecation'
|
28
|
+
require 'engineyard-serverside/future'
|
30
29
|
|
31
30
|
module EY
|
32
31
|
module Serverside
|
@@ -4,13 +4,6 @@ require 'pathname'
|
|
4
4
|
module EY
|
5
5
|
module Serverside
|
6
6
|
class CLI < Thor
|
7
|
-
include Dataflow
|
8
|
-
|
9
|
-
def self.start(*)
|
10
|
-
super
|
11
|
-
rescue RemoteFailure
|
12
|
-
exit(1)
|
13
|
-
end
|
14
7
|
|
15
8
|
method_option :migrate, :type => :string,
|
16
9
|
:desc => "Run migrations with this deploy",
|
@@ -63,7 +56,7 @@ module EY
|
|
63
56
|
EY::Serverside::LoggedOutput.verbose = options[:verbose]
|
64
57
|
EY::Serverside::LoggedOutput.logfile = File.join(ENV['HOME'], "#{options[:app]}-deploy.log")
|
65
58
|
|
66
|
-
|
59
|
+
propagate
|
67
60
|
|
68
61
|
EY::Serverside::Deploy.new(config).send(default_task)
|
69
62
|
end
|
@@ -144,7 +137,7 @@ module EY
|
|
144
137
|
|
145
138
|
EY::Serverside::Server.load_all_from_array(assemble_instance_hashes(config))
|
146
139
|
|
147
|
-
|
140
|
+
propagate
|
148
141
|
|
149
142
|
EY::Serverside::Server.all.each do |server|
|
150
143
|
server.sync_directory app_dir
|
@@ -190,7 +183,7 @@ module EY
|
|
190
183
|
config = EY::Serverside::Deploy::Configuration.new(options)
|
191
184
|
EY::Serverside::Server.load_all_from_array(assemble_instance_hashes(config))
|
192
185
|
|
193
|
-
|
186
|
+
propagate
|
194
187
|
|
195
188
|
EY::Serverside::Deploy.new(config).restart_with_maintenance_page
|
196
189
|
end
|
@@ -212,34 +205,25 @@ module EY
|
|
212
205
|
|
213
206
|
desc "propagate", "Propagate the engineyard-serverside gem to the other instances in the cluster. This will install exactly version #{EY::Serverside::VERSION}."
|
214
207
|
def propagate
|
215
|
-
|
216
|
-
|
208
|
+
name = "engineyard-serverside"
|
209
|
+
version = EY::Serverside::VERSION
|
210
|
+
gem_filename = "#{name}-#{version}.gem"
|
217
211
|
local_gem_file = File.join(Gem.dir, 'cache', gem_filename)
|
218
212
|
remote_gem_file = File.join(Dir.tmpdir, gem_filename)
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
has_gem_cmd = "#{gem_binary} list engineyard-serverside | grep \"engineyard-serverside\" | egrep -q '#{egrep_escaped_version}[,)]'"
|
229
|
-
|
230
|
-
if !server.run(has_gem_cmd) # doesn't have this exact version
|
231
|
-
puts "~> Installing engineyard-serverside on #{server.hostname}"
|
232
|
-
|
233
|
-
system(Escape.shell_command([
|
234
|
-
'scp', '-i', "#{ENV['HOME']}/.ssh/internal",
|
235
|
-
"-o", "StrictHostKeyChecking=no",
|
236
|
-
local_gem_file,
|
237
|
-
"#{config.user}@#{server.hostname}:#{remote_gem_file}",
|
238
|
-
]))
|
239
|
-
server.run("sudo #{gem_binary} install --no-rdoc --no-ri '#{remote_gem_file}'")
|
240
|
-
end
|
213
|
+
|
214
|
+
servers = EY::Serverside::Server.all.find_all { |server| !server.local? }
|
215
|
+
|
216
|
+
futures = EY::Serverside::Future.call(servers) do |server|
|
217
|
+
installed = server.gem?(name, version)
|
218
|
+
unless installed
|
219
|
+
info "~> Installing #{name} on #{server.hostname}"
|
220
|
+
server.copy(local_gem_file, remote_gem_file)
|
221
|
+
installed = server.install_gem(remote_gem_file)
|
241
222
|
end
|
242
|
-
|
223
|
+
installed
|
224
|
+
end
|
225
|
+
|
226
|
+
EY::Serverside::Future.success?(futures)
|
243
227
|
end
|
244
228
|
|
245
229
|
private
|
@@ -163,9 +163,10 @@ To fix this problem, commit your Gemfile.lock to your repository and redeploy.
|
|
163
163
|
# task
|
164
164
|
def push_code
|
165
165
|
info "~> Pushing code to all servers"
|
166
|
-
|
167
|
-
|
168
|
-
end
|
166
|
+
futures = EY::Serverside::Future.call(EY::Serverside::Server.all) do |server|
|
167
|
+
server.sync_directory(config.repository_cache)
|
168
|
+
end
|
169
|
+
EY::Serverside::Future.success?(futures)
|
169
170
|
end
|
170
171
|
|
171
172
|
# task
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module EY
|
2
|
+
module Serverside
|
3
|
+
class Future
|
4
|
+
def self.success?(futures)
|
5
|
+
futures.empty? || futures.all? {|f| f.success?}
|
6
|
+
end
|
7
|
+
|
8
|
+
def initialize(server, *args, &block)
|
9
|
+
@server = server
|
10
|
+
@args = args
|
11
|
+
@block = block
|
12
|
+
end
|
13
|
+
|
14
|
+
def success?
|
15
|
+
@value == true
|
16
|
+
end
|
17
|
+
|
18
|
+
def error?
|
19
|
+
!success?
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
if defined?(Fiber)
|
24
|
+
require 'engineyard-serverside/futures/celluloid'
|
25
|
+
else
|
26
|
+
require 'engineyard-serverside/futures/dataflow'
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module EY
|
2
|
+
module Serverside
|
3
|
+
$LOAD_PATH.unshift File.expand_path('../../vendor/celluloid/lib', File.dirname(__FILE__))
|
4
|
+
require 'celluloid'
|
5
|
+
class Future
|
6
|
+
def self.call(servers, *args, &block)
|
7
|
+
futures = servers.map do |server|
|
8
|
+
new(server, *args, &block)
|
9
|
+
end
|
10
|
+
|
11
|
+
futures.each {|f| f.call}
|
12
|
+
futures
|
13
|
+
end
|
14
|
+
|
15
|
+
def future
|
16
|
+
Celluloid::Future.new(@server, *@args, &@block)
|
17
|
+
end
|
18
|
+
|
19
|
+
def call
|
20
|
+
# Celluloid needs to call the block explicitely
|
21
|
+
@value ||= future.call
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module EY
|
2
|
+
module Serverside
|
3
|
+
$LOAD_PATH.unshift File.expand_path('../../vendor/dataflow', File.dirname(__FILE__))
|
4
|
+
require 'dataflow'
|
5
|
+
|
6
|
+
class Future
|
7
|
+
extend Dataflow
|
8
|
+
|
9
|
+
def self.call(servers, *args, &block)
|
10
|
+
futures = []
|
11
|
+
# Dataflow needs to call `barrier` and `need_later` in the same object
|
12
|
+
barrier(*servers.map do |server|
|
13
|
+
future = new(server, *args, &block)
|
14
|
+
futures << future
|
15
|
+
|
16
|
+
need_later { future.call }
|
17
|
+
end)
|
18
|
+
|
19
|
+
futures
|
20
|
+
end
|
21
|
+
|
22
|
+
def future
|
23
|
+
@block.call(@server, *@args)
|
24
|
+
end
|
25
|
+
|
26
|
+
def call
|
27
|
+
@value ||= future
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -83,12 +83,37 @@ module EY
|
|
83
83
|
if local?
|
84
84
|
logged_system(command)
|
85
85
|
else
|
86
|
-
logged_system(ssh_command +
|
86
|
+
logged_system(ssh_command + Escape.shell_command(["#{user}@#{hostname}", command]))
|
87
87
|
end
|
88
88
|
end
|
89
89
|
|
90
|
+
def copy(local_file, remote_file)
|
91
|
+
logged_system(scp_command + Escape.shell_command([local_file, "#{user}@#{hostname}:#{remote_file}"]))
|
92
|
+
end
|
93
|
+
|
90
94
|
def ssh_command
|
91
|
-
"ssh
|
95
|
+
"ssh #{ssh_options} "
|
96
|
+
end
|
97
|
+
|
98
|
+
def scp_command
|
99
|
+
"scp #{ssh_options} "
|
100
|
+
end
|
101
|
+
|
102
|
+
def ssh_options
|
103
|
+
"-i #{ENV['HOME']}/.ssh/internal -o StrictHostKeyChecking=no -o PasswordAuthentication=no"
|
104
|
+
end
|
105
|
+
|
106
|
+
def gem?(name, version)
|
107
|
+
run("#{gem_command} list -i #{name} -v '#{version}'")
|
108
|
+
end
|
109
|
+
|
110
|
+
def install_gem(path)
|
111
|
+
# resin + ruby 1.8.6 need sudo privileges to install gems
|
112
|
+
run("sudo #{gem_command} install -q --no-ri --no-rdoc #{path}")
|
113
|
+
end
|
114
|
+
|
115
|
+
def gem_command
|
116
|
+
File.join(Gem.default_bindir, 'gem')
|
92
117
|
end
|
93
118
|
|
94
119
|
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
module EY
|
2
2
|
module Serverside
|
3
3
|
class Task
|
4
|
-
include Dataflow
|
5
4
|
|
6
5
|
attr_reader :config
|
7
6
|
alias :c :config
|
@@ -51,18 +50,18 @@ module EY
|
|
51
50
|
|
52
51
|
private
|
53
52
|
|
54
|
-
def run_on_roles(cmd, wrapper=%w[sh -l -c])
|
55
|
-
|
56
|
-
|
57
|
-
|
53
|
+
def run_on_roles(cmd, wrapper=%w[sh -l -c], &block)
|
54
|
+
servers = EY::Serverside::Server.from_roles(@roles)
|
55
|
+
futures = EY::Serverside::Future.call(servers, block_given?) do |server, exec_block|
|
56
|
+
to_run = exec_block ? block.call(server, cmd.dup) : cmd
|
57
|
+
server.run(Escape.shell_command(wrapper + [to_run]))
|
58
58
|
end
|
59
|
-
barrier *results
|
60
|
-
# MRI's truthiness check is an internal C thing that does not call
|
61
|
-
# any methods... so Dataflow cannot proxy it & we must "x == true"
|
62
|
-
# Rubinius, wherefore art thou!?
|
63
|
-
results.all?{|x| x == true } || raise(EY::Serverside::RemoteFailure.new(cmd))
|
64
|
-
end
|
65
59
|
|
60
|
+
unless EY::Serverside::Future.success?(futures)
|
61
|
+
failures = futures.select {|f| f.error? }.map {|f| f.inspect}.join("\n")
|
62
|
+
raise EY::Serverside::RemoteFailure.new(failures)
|
63
|
+
end
|
64
|
+
end
|
66
65
|
end
|
67
66
|
end
|
68
67
|
end
|
@@ -0,0 +1,261 @@
|
|
1
|
+
require 'logger'
|
2
|
+
require 'thread'
|
3
|
+
|
4
|
+
module Celluloid
|
5
|
+
@logger = Logger.new STDERR
|
6
|
+
|
7
|
+
class << self
|
8
|
+
attr_accessor :logger # Thread-safe logger class
|
9
|
+
|
10
|
+
def included(klass)
|
11
|
+
klass.send :extend, ClassMethods
|
12
|
+
end
|
13
|
+
|
14
|
+
# Are we currently inside of an actor?
|
15
|
+
def actor?
|
16
|
+
!!Thread.current[:actor]
|
17
|
+
end
|
18
|
+
|
19
|
+
# Obtain the currently running actor (if one exists)
|
20
|
+
def current_actor
|
21
|
+
actor = Thread.current[:actor]
|
22
|
+
raise NotActorError, "not in actor scope" unless actor
|
23
|
+
actor.proxy
|
24
|
+
end
|
25
|
+
alias_method :current, :current_actor
|
26
|
+
|
27
|
+
# Receive an asynchronous message
|
28
|
+
def receive(timeout = nil, &block)
|
29
|
+
actor = Thread.current[:actor]
|
30
|
+
if actor
|
31
|
+
actor.receive(timeout, &block)
|
32
|
+
else
|
33
|
+
Thread.mailbox.receive(timeout, &block)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# Sleep letting the actor continue processing messages
|
38
|
+
def sleep(interval)
|
39
|
+
actor = Thread.current[:actor]
|
40
|
+
if actor
|
41
|
+
actor.sleep(interval)
|
42
|
+
else
|
43
|
+
Kernel.sleep interval
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# Obtain a hash of active tasks to their current activities
|
48
|
+
def tasks
|
49
|
+
actor = Thread.current[:actor]
|
50
|
+
raise NotActorError, "not in actor scope" unless actor
|
51
|
+
actor.tasks
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# Class methods added to classes which include Celluloid
|
56
|
+
module ClassMethods
|
57
|
+
# Create a new actor
|
58
|
+
def new(*args, &block)
|
59
|
+
proxy = Actor.new(allocate).proxy
|
60
|
+
proxy.send(:initialize, *args, &block)
|
61
|
+
proxy
|
62
|
+
end
|
63
|
+
alias_method :spawn, :new
|
64
|
+
|
65
|
+
# Create a new actor and link to the current one
|
66
|
+
def new_link(*args, &block)
|
67
|
+
current_actor = Celluloid.current_actor
|
68
|
+
raise NotActorError, "can't link outside actor context" unless current_actor
|
69
|
+
|
70
|
+
proxy = Actor.new(allocate).proxy
|
71
|
+
current_actor.link proxy
|
72
|
+
proxy.send(:initialize, *args, &block)
|
73
|
+
proxy
|
74
|
+
end
|
75
|
+
alias_method :spawn_link, :new_link
|
76
|
+
|
77
|
+
# Create a supervisor which ensures an instance of an actor will restart
|
78
|
+
# an actor if it fails
|
79
|
+
def supervise(*args, &block)
|
80
|
+
Supervisor.supervise(self, *args, &block)
|
81
|
+
end
|
82
|
+
|
83
|
+
# Create a supervisor which ensures an instance of an actor will restart
|
84
|
+
# an actor if it fails, and keep the actor registered under a given name
|
85
|
+
def supervise_as(name, *args, &block)
|
86
|
+
Supervisor.supervise_as(name, self, *args, &block)
|
87
|
+
end
|
88
|
+
|
89
|
+
# Trap errors from actors we're linked to when they exit
|
90
|
+
def trap_exit(callback)
|
91
|
+
@exit_handler = callback.to_sym
|
92
|
+
end
|
93
|
+
|
94
|
+
# Obtain the exit handler for this actor
|
95
|
+
attr_reader :exit_handler
|
96
|
+
|
97
|
+
# Configure a custom mailbox factory
|
98
|
+
def use_mailbox(klass = nil, &block)
|
99
|
+
if block
|
100
|
+
define_method(:mailbox_factory, &block)
|
101
|
+
else
|
102
|
+
define_method(:mailbox_factory) { klass.new }
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
#
|
108
|
+
# Instance methods
|
109
|
+
#
|
110
|
+
|
111
|
+
# Is this actor alive?
|
112
|
+
def alive?
|
113
|
+
Thread.current[:actor].alive?
|
114
|
+
end
|
115
|
+
|
116
|
+
# Raise an exception in caller context, but stay running
|
117
|
+
def abort(cause)
|
118
|
+
raise AbortError.new(cause)
|
119
|
+
end
|
120
|
+
|
121
|
+
# Terminate this actor
|
122
|
+
def terminate
|
123
|
+
Thread.current[:actor].terminate
|
124
|
+
end
|
125
|
+
|
126
|
+
def inspect
|
127
|
+
str = "#<Celluloid::Actor(#{self.class}:0x#{object_id.to_s(16)})"
|
128
|
+
ivars = instance_variables.map do |ivar|
|
129
|
+
"#{ivar}=#{instance_variable_get(ivar).inspect}"
|
130
|
+
end
|
131
|
+
|
132
|
+
str << " " << ivars.join(' ') unless ivars.empty?
|
133
|
+
str << ">"
|
134
|
+
end
|
135
|
+
|
136
|
+
# Send a signal with the given name to all waiting methods
|
137
|
+
def signal(name, value = nil)
|
138
|
+
Thread.current[:actor].signal name, value
|
139
|
+
end
|
140
|
+
|
141
|
+
# Wait for the given signal
|
142
|
+
def wait(name)
|
143
|
+
Thread.current[:actor].wait name
|
144
|
+
end
|
145
|
+
|
146
|
+
# Obtain the current_actor
|
147
|
+
def current_actor
|
148
|
+
Celluloid.current_actor
|
149
|
+
end
|
150
|
+
|
151
|
+
# Obtain the running tasks for this actor
|
152
|
+
def tasks
|
153
|
+
Celluloid.tasks
|
154
|
+
end
|
155
|
+
|
156
|
+
# Obtain the Ruby object the actor is wrapping. This should ONLY be used
|
157
|
+
# for a limited set of use cases like runtime metaprogramming. Interacting
|
158
|
+
# directly with the wrapped object foregoes any kind of thread safety that
|
159
|
+
# Celluloid would ordinarily provide you, and the object is guaranteed to
|
160
|
+
# be shared with at least the actor thread. Tread carefully.
|
161
|
+
def wrapped_object; self; end
|
162
|
+
|
163
|
+
# Obtain the Celluloid::Links for this actor
|
164
|
+
def links
|
165
|
+
Thread.current[:actor].links
|
166
|
+
end
|
167
|
+
|
168
|
+
# Link this actor to another, allowing it to crash or react to errors
|
169
|
+
def link(actor)
|
170
|
+
actor.notify_link current_actor
|
171
|
+
notify_link actor
|
172
|
+
end
|
173
|
+
|
174
|
+
# Remove links to another actor
|
175
|
+
def unlink(actor)
|
176
|
+
actor.notify_unlink current_actor
|
177
|
+
notify_unlink actor
|
178
|
+
end
|
179
|
+
|
180
|
+
def notify_link(actor)
|
181
|
+
links << actor
|
182
|
+
end
|
183
|
+
|
184
|
+
def notify_unlink(actor)
|
185
|
+
links.delete actor
|
186
|
+
end
|
187
|
+
|
188
|
+
# Is this actor linked to another?
|
189
|
+
def linked_to?(actor)
|
190
|
+
Thread.current[:actor].links.include? actor
|
191
|
+
end
|
192
|
+
|
193
|
+
# Receive an asynchronous message via the actor protocol
|
194
|
+
def receive(timeout = nil, &block)
|
195
|
+
Celluloid.receive(timeout, &block)
|
196
|
+
end
|
197
|
+
|
198
|
+
# Sleep while letting the actor continue to receive messages
|
199
|
+
def sleep(interval)
|
200
|
+
Celluloid.sleep(interval)
|
201
|
+
end
|
202
|
+
|
203
|
+
# Call a block after a given interval
|
204
|
+
def after(interval, &block)
|
205
|
+
Thread.current[:actor].after(interval, &block)
|
206
|
+
end
|
207
|
+
|
208
|
+
# Perform a blocking or computationally intensive action inside an
|
209
|
+
# asynchronous thread pool, allowing the caller to continue processing other
|
210
|
+
# messages in its mailbox in the meantime
|
211
|
+
def async(&block)
|
212
|
+
# This implementation relies on the present implementation of
|
213
|
+
# Celluloid::Future, which uses an Actor to run the block
|
214
|
+
Future.new(&block).value
|
215
|
+
end
|
216
|
+
|
217
|
+
# Process async calls via method_missing
|
218
|
+
def method_missing(meth, *args, &block)
|
219
|
+
# bang methods are async calls
|
220
|
+
if meth.to_s.match(/!$/)
|
221
|
+
unbanged_meth = meth.to_s.sub(/!$/, '')
|
222
|
+
call = AsyncCall.new(@mailbox, unbanged_meth, args, block)
|
223
|
+
|
224
|
+
begin
|
225
|
+
Thread.current[:actor].mailbox << call
|
226
|
+
rescue MailboxError
|
227
|
+
# Silently swallow asynchronous calls to dead actors. There's no way
|
228
|
+
# to reliably generate DeadActorErrors for async calls, so users of
|
229
|
+
# async calls should find other ways to deal with actors dying
|
230
|
+
# during an async call (i.e. linking/supervisors)
|
231
|
+
end
|
232
|
+
|
233
|
+
return # casts are async and return immediately
|
234
|
+
end
|
235
|
+
|
236
|
+
super
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
require 'celluloid/version'
|
241
|
+
require 'celluloid/actor_proxy'
|
242
|
+
require 'celluloid/calls'
|
243
|
+
require 'celluloid/core_ext'
|
244
|
+
require 'celluloid/events'
|
245
|
+
require 'celluloid/fiber'
|
246
|
+
require 'celluloid/fsm'
|
247
|
+
require 'celluloid/links'
|
248
|
+
require 'celluloid/logger'
|
249
|
+
require 'celluloid/mailbox'
|
250
|
+
require 'celluloid/receivers'
|
251
|
+
require 'celluloid/registry'
|
252
|
+
require 'celluloid/responses'
|
253
|
+
require 'celluloid/signals'
|
254
|
+
require 'celluloid/task'
|
255
|
+
require 'celluloid/timers'
|
256
|
+
|
257
|
+
require 'celluloid/actor'
|
258
|
+
require 'celluloid/actor_pool'
|
259
|
+
require 'celluloid/supervisor'
|
260
|
+
require 'celluloid/future'
|
261
|
+
require 'celluloid/application'
|