Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
...
Checking mergeability… Don't worry, you can still create the pull request.
  • 15 commits
  • 186 files changed
  • 3 commit comments
  • 6 contributors
Showing with 23,609 additions and 1,945 deletions.
  1. +16 −0 ChangeLog.md
  2. +1 −0  engineyard-serverside.gemspec
  3. +19 −17 lib/engineyard-serverside.rb
  4. +38 −30 lib/engineyard-serverside/cli.rb
  5. +3 −27 lib/engineyard-serverside/configuration.rb
  6. +30 −6 lib/engineyard-serverside/deploy.rb
  7. +0 −29 lib/engineyard-serverside/future.rb
  8. +0 −25 lib/engineyard-serverside/futures/celluloid.rb
  9. +0 −31 lib/engineyard-serverside/futures/dataflow.rb
  10. +6 −2 lib/engineyard-serverside/lockfile_parser.rb
  11. +12 −4 lib/engineyard-serverside/logged_output.rb
  12. +2 −26 lib/engineyard-serverside/server.rb
  13. +11 −11 lib/engineyard-serverside/task.rb
  14. +1 −1  lib/engineyard-serverside/version.rb
  15. +0 −261 lib/vendor/celluloid/lib/celluloid.rb
  16. +0 −242 lib/vendor/celluloid/lib/celluloid/actor.rb
  17. +0 −54 lib/vendor/celluloid/lib/celluloid/actor_pool.rb
  18. +0 −75 lib/vendor/celluloid/lib/celluloid/actor_proxy.rb
  19. +0 −78 lib/vendor/celluloid/lib/celluloid/application.rb
  20. +0 −94 lib/vendor/celluloid/lib/celluloid/calls.rb
  21. +0 −14 lib/vendor/celluloid/lib/celluloid/core_ext.rb
  22. +0 −14 lib/vendor/celluloid/lib/celluloid/events.rb
  23. +0 −33 lib/vendor/celluloid/lib/celluloid/fiber.rb
  24. +0 −141 lib/vendor/celluloid/lib/celluloid/fsm.rb
  25. +0 −60 lib/vendor/celluloid/lib/celluloid/future.rb
  26. +0 −61 lib/vendor/celluloid/lib/celluloid/links.rb
  27. +0 −32 lib/vendor/celluloid/lib/celluloid/logger.rb
  28. +0 −124 lib/vendor/celluloid/lib/celluloid/mailbox.rb
  29. +0 −66 lib/vendor/celluloid/lib/celluloid/receivers.rb
  30. +0 −33 lib/vendor/celluloid/lib/celluloid/registry.rb
  31. +0 −26 lib/vendor/celluloid/lib/celluloid/responses.rb
  32. +0 −2  lib/vendor/celluloid/lib/celluloid/rspec.rb
  33. +0 −50 lib/vendor/celluloid/lib/celluloid/signals.rb
  34. +0 −57 lib/vendor/celluloid/lib/celluloid/supervisor.rb
  35. +0 −73 lib/vendor/celluloid/lib/celluloid/task.rb
  36. +0 −33 lib/vendor/celluloid/lib/celluloid/tcp_server.rb
  37. +0 −109 lib/vendor/celluloid/lib/celluloid/timers.rb
  38. +0 −4 lib/vendor/celluloid/lib/celluloid/version.rb
  39. +52 −0 lib/vendor/dataflow/HISTORY
  40. +19 −0 lib/vendor/dataflow/LICENSE
  41. +290 −0 lib/vendor/dataflow/README.textile
  42. +36 −0 lib/vendor/dataflow/Rakefile
  43. +9 −0 lib/vendor/dataflow/examples/barrier.rb
  44. +17 −0 lib/vendor/dataflow/examples/data_driven.rb
  45. +13 −0 lib/vendor/dataflow/examples/dataflow_http_gets.rb
  46. +20 −0 lib/vendor/dataflow/examples/flow.rb
  47. +12 −0 lib/vendor/dataflow/examples/future_http_gets.rb
  48. +11 −0 lib/vendor/dataflow/examples/future_queue.rb
  49. +15 −0 lib/vendor/dataflow/examples/instance_variables.rb
  50. +9 −0 lib/vendor/dataflow/examples/laziness.rb
  51. +11 −0 lib/vendor/dataflow/examples/local_variables.rb
  52. +26 −0 lib/vendor/dataflow/examples/messages.rb
  53. +13 −0 lib/vendor/dataflow/examples/port_http_gets.rb
  54. +10 −0 lib/vendor/dataflow/examples/port_send.rb
  55. +21 −0 lib/vendor/dataflow/examples/ring.rb
  56. +28 −0 lib/vendor/dataflow/spec/actor_spec.rb
  57. +21 −0 lib/vendor/dataflow/spec/anonymous_variables_spec.rb
  58. +25 −0 lib/vendor/dataflow/spec/barrier_spec.rb
  59. +55 −0 lib/vendor/dataflow/spec/by_need_spec.rb
  60. +151 −0 lib/vendor/dataflow/spec/dataflow_spec.rb
  61. +40 −0 lib/vendor/dataflow/spec/equality_spec.rb
  62. +25 −0 lib/vendor/dataflow/spec/flow_spec.rb
  63. +28 −0 lib/vendor/dataflow/spec/forker_spec.rb
  64. +31 −0 lib/vendor/dataflow/spec/future_queue_spec.rb
  65. +19 −0 lib/vendor/dataflow/spec/inspect_spec.rb
  66. +12 −0 lib/vendor/dataflow/spec/need_later_spec.rb
  67. +26 −0 lib/vendor/dataflow/spec/port_spec.rb
  68. +1 −0  lib/vendor/dataflow/spec/spec.opts
  69. +10 −0 lib/vendor/dataflow/spec/spec_helper.rb
  70. +21 −0 lib/vendor/escape/Readme
  71. +631 −0 lib/vendor/escape/doc_include/template/qualitysmith.rb
  72. +166 −0 lib/vendor/json_pure/CHANGES
  73. +58 −0 lib/vendor/json_pure/COPYING
  74. +340 −0 lib/vendor/json_pure/GPL
  75. +358 −0 lib/vendor/json_pure/README
  76. +292 −0 lib/vendor/json_pure/Rakefile
  77. +1 −0  lib/vendor/json_pure/TODO
  78. +1 −0  lib/vendor/json_pure/VERSION
  79. +52 −0 lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkComparison.log
  80. +1,000 −0 lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_fast-autocorrelation.dat
  81. +1,001 −0 lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_fast.dat
  82. +900 −0 lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_pretty-autocorrelation.dat
  83. +901 −0 lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_pretty.dat
  84. +1,000 −0 lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_safe-autocorrelation.dat
  85. +1,001 −0 lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_safe.dat
  86. +261 −0 lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt.log
  87. +1,000 −0 lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_fast-autocorrelation.dat
  88. +1,001 −0 lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_fast.dat
  89. +1,000 −0 ...vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_pretty-autocorrelation.dat
  90. +1,001 −0 lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_pretty.dat
  91. +1,000 −0 lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_safe-autocorrelation.dat
  92. +1,001 −0 lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_safe.dat
  93. +262 −0 lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure.log
  94. +1,000 −0 lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkRails#generator-autocorrelation.dat
  95. +1,001 −0 lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkRails#generator.dat
  96. +82 −0 lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkRails.log
  97. +34 −0 lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkComparison.log
  98. +900 −0 lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkExt#parser-autocorrelation.dat
  99. +901 −0 lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkExt#parser.dat
  100. +81 −0 lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkExt.log
  101. +1,000 −0 lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkPure#parser-autocorrelation.dat
  102. +1,001 −0 lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkPure#parser.dat
  103. +82 −0 lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkPure.log
  104. +1,000 −0 lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkRails#parser-autocorrelation.dat
  105. +1,001 −0 lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkRails#parser.dat
  106. +82 −0 lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkRails.log
Sorry, we could not display the entire diff because it was too big.
View
16 ChangeLog.md
@@ -4,6 +4,22 @@
*
+## v1.5.26 (2012-01-21)
+
+ * Adds timestamps to deploy logs
+
+## v1.5.25 (2012-01-13)
+
+ *
+
+## v1.5.24 (2012-01-12)
+
+ *
+
+## v1.5.23 (2012-01-11)
+
+ *
+
## v1.5.22 (2011-12-09)
* Add LANG to restart command.
View
1  engineyard-serverside.gemspec
@@ -20,6 +20,7 @@ Gem::Specification.new do |s|
s.add_development_dependency('rspec', '1.3.2')
s.add_development_dependency('rake', '>=0.9.2.2')
s.add_development_dependency('rdoc')
+ s.add_development_dependency('timecop')
s.required_rubygems_version = %q{>= 1.3.6}
s.test_files = Dir.glob("spec/**/*")
View
36 lib/engineyard-serverside.rb
@@ -1,15 +1,21 @@
-# encoding: utf-8
+if String.instance_methods.include?(:force_encoding)
+ $string_encodings = true
+else
+ # KCODE is gone in 1.9-like implementations, but we
+ # still need to set it for 1.8.
+ $KCODE = 'U'
+ $string_encodings = false
+end
+$LOAD_PATH.unshift File.expand_path('vendor/thor/lib', File.dirname(__FILE__))
+$LOAD_PATH.unshift File.expand_path('vendor/open4/lib', File.dirname(__FILE__))
$LOAD_PATH.unshift File.expand_path('vendor/escape/lib', File.dirname(__FILE__))
$LOAD_PATH.unshift File.expand_path('vendor/json_pure/lib', File.dirname(__FILE__))
-$LOAD_PATH.unshift File.expand_path('vendor/open4/lib', File.dirname(__FILE__))
-$LOAD_PATH.unshift File.expand_path('vendor/thor/lib', File.dirname(__FILE__))
+$LOAD_PATH.unshift File.expand_path('vendor/dataflow', File.dirname(__FILE__))
require 'escape'
require 'json'
-require 'tmpdir'
-require 'thor'
-require 'open4'
+require 'dataflow'
require 'engineyard-serverside/version'
require 'engineyard-serverside/strategies/git'
@@ -21,7 +27,6 @@
require 'engineyard-serverside/cli'
require 'engineyard-serverside/configuration'
require 'engineyard-serverside/deprecation'
-require 'engineyard-serverside/future'
module EY
module Serverside
@@ -55,16 +60,13 @@ def self.dna_path
end
def self.read_encoded_dna
- encoded_dna = '{}'
- force_unicode = encoded_dna.respond_to?(:force_encoding)
- $KCODE = 'U' unless force_unicode
-
- if File.exist?(dna_path)
- encoded_dna = `sudo cat #{dna_path}`
- encoded_dna.force_encoding('UTF-8') if force_unicode
- end
-
- encoded_dna
+ json = if File.exist?(dna_path)
+ `sudo cat #{dna_path}`
+ else
+ '{}'
+ end
+ json.force_encoding('UTF-8') if $string_encodings
+ json
end
end
end
View
68 lib/engineyard-serverside/cli.rb
@@ -1,8 +1,16 @@
+require 'thor'
require 'pathname'
module EY
module Serverside
class CLI < Thor
+ include Dataflow
+
+ def self.start(*)
+ super
+ rescue RemoteFailure
+ exit(1)
+ end
method_option :migrate, :type => :string,
:desc => "Run migrations with this deploy",
@@ -48,14 +56,14 @@ class CLI < Thor
:aliases => ["-v"]
desc "deploy", "Deploy code from /data/<app>"
- def deploy(default_task = :deploy)
+ def deploy(default_task=:deploy)
config = EY::Serverside::Deploy::Configuration.new(options)
EY::Serverside::Server.load_all_from_array(assemble_instance_hashes(config))
EY::Serverside::LoggedOutput.verbose = options[:verbose]
EY::Serverside::LoggedOutput.logfile = File.join(ENV['HOME'], "#{options[:app]}-deploy.log")
- propagate
+ invoke :propagate
EY::Serverside::Deploy.new(config).send(default_task)
end
@@ -136,7 +144,7 @@ def integrate
EY::Serverside::Server.load_all_from_array(assemble_instance_hashes(config))
- propagate
+ invoke :propagate
EY::Serverside::Server.all.each do |server|
server.sync_directory app_dir
@@ -182,7 +190,7 @@ def restart
config = EY::Serverside::Deploy::Configuration.new(options)
EY::Serverside::Server.load_all_from_array(assemble_instance_hashes(config))
- propagate
+ invoke :propagate
EY::Serverside::Deploy.new(config).restart_with_maintenance_page
end
@@ -204,22 +212,34 @@ def install_bundler(version)
desc "propagate", "Propagate the engineyard-serverside gem to the other instances in the cluster. This will install exactly version #{EY::Serverside::VERSION}."
def propagate
- ey_server_side = Dependency.new('engineyard-serverside', EY::Serverside::VERSION)
- servers = EY::Serverside::Server.all.find_all { |server| !server.local? }
-
- futures = EY::Serverside::Future.call(servers) do |server|
- installed = server.gem?(ey_server_side.name, ey_server_side.version)
- unless installed
- unless server.gem?(ey_server_side.name, ey_server_side.version)
- puts "~> Installing #{ey_server_side.name} on #{server.hostname}"
- server.copy(ey_server_side.local_path, ey_server_side.remote_path)
- installed = server.install_gem(ey_server_side.remote_path)
+ config = EY::Serverside::Deploy::Configuration.new
+ gem_filename = "engineyard-serverside-#{EY::Serverside::VERSION}.gem"
+ local_gem_file = File.join(Gem.dir, 'cache', gem_filename)
+ remote_gem_file = File.join(Dir.tmpdir, gem_filename)
+ gem_binary = File.join(Gem.default_bindir, 'gem')
+
+ barrier(*(EY::Serverside::Server.all.find_all do |server|
+ !server.local? # of course this machine has it
+ end.map do |server|
+ need_later do
+ egrep_escaped_version = EY::Serverside::VERSION.gsub(/\./, '\.')
+ # the [,)] is to stop us from looking for e.g. 0.5.1, seeing
+ # 0.5.11, and mistakenly thinking 0.5.1 is there
+ has_gem_cmd = "#{gem_binary} list engineyard-serverside | grep \"engineyard-serverside\" | egrep -q '#{egrep_escaped_version}[,)]'"
+
+ if !server.run(has_gem_cmd) # doesn't have this exact version
+ puts "~> Installing engineyard-serverside on #{server.hostname}"
+
+ system(Escape.shell_command([
+ 'scp', '-i', "#{ENV['HOME']}/.ssh/internal",
+ "-o", "StrictHostKeyChecking=no",
+ local_gem_file,
+ "#{config.user}@#{server.hostname}:#{remote_gem_file}",
+ ]))
+ server.run("sudo #{gem_binary} install --no-rdoc --no-ri '#{remote_gem_file}'")
end
end
- installed
- end
-
- EY::Serverside::Future.success?(futures)
+ end))
end
private
@@ -233,18 +253,6 @@ def assemble_instance_hashes(config)
}
}
end
-
- class Dependency
- attr_reader :name, :version
- def initialize(name, version)
- @name = name
- @version = version
- end
-
- def gemname; "#{name}-#{version}.gem"; end
- def local_path; File.expand_path(File.join('cache', gemname), Gem.dir); end
- def remote_path; File.expand_path(gemname, Dir.tmpdir); end
- end
end
end
end
View
30 lib/engineyard-serverside/configuration.rb
@@ -1,37 +1,13 @@
+require 'json'
+require 'thor'
module EY
module Serverside
- # Really simple and hacked implementation that works for the 99.9999% of the cases
- class HashWithIndifferentAccess
- def initialize(hash = {})
- @internal = {}
- hash.each do |k, v|
- @internal[k.to_s] = v
- end
- end
- def [](name)
- @internal[name.to_s]
- end
- def []=(name, value)
- @internal[name.to_s] = value
- end
-
- def method_missing(method, *args, &block)
- if @internal.key?(method.to_s)
- @internal[method.to_s]
- else
- @internal.send(method, args, &block)
- end
- end
- end
-
class Deploy::Configuration
- require 'json'
-
DEFAULT_CONFIG = Thor::CoreExt::HashWithIndifferentAccess.new({
"branch" => "master",
"strategy" => "Git",
- "bundle_without" => "test development"
+ "bundle_without" => "test development",
})
attr_reader :configuration
View
36 lib/engineyard-serverside/deploy.rb
@@ -30,6 +30,7 @@ def cached_deploy
create_revision_file
run_with_callbacks(:bundle)
setup_services
+ check_for_ey_config
symlink_configs
conditionally_enable_maintenance_page
run_with_callbacks(:migrate)
@@ -52,6 +53,23 @@ def cached_deploy
raise
end
+ def parse_configured_services
+ result = YAML.load_file "#{c.shared_path}/config/ey_services_config_deploy.yml"
+ return {} unless result.is_a?(Hash)
+ result
+ rescue
+ {}
+ end
+
+ def check_for_ey_config
+ if gemfile? && lockfile
+ configured_services = parse_configured_services
+ if !configured_services.empty? && !lockfile.has_ey_config?
+ warning "Gemfile.lock does not contain ey_config. Add it to get EY::Config access to: #{configured_services.keys.join(', ')}."
+ end
+ end
+ end
+
def check_repository
if gemfile?
info "~> Gemfile found."
@@ -145,10 +163,9 @@ def run_with_callbacks(task)
# task
def push_code
info "~> Pushing code to all servers"
- futures = EY::Serverside::Future.call(EY::Serverside::Server.all) do |server|
- server.sync_directory(config.repository_cache)
- end
- EY::Serverside::Future.success?(futures)
+ barrier *(EY::Serverside::Server.all.map do |server|
+ need_later { server.sync_directory(config.repository_cache) }
+ end)
end
# task
@@ -287,6 +304,7 @@ def node_package_manager_command_check
def setup_services
info "~> Setting up external services."
+ previously_configured_services = parse_configured_services
begin
sudo(services_command_check)
rescue StandardError => e
@@ -295,11 +313,13 @@ def setup_services
end
sudo(services_setup_command)
rescue StandardError => e
- warning <<-WARNING
+ unless previously_configured_services.empty?
+ warning <<-WARNING
External services configuration not updated. Using previous version.
Deploy again if your services configuration appears incomplete or out of date.
#{e}
- WARNING
+ WARNING
+ end
end
def symlink_configs(release_to_link=c.release_path)
@@ -357,6 +377,10 @@ def callback(what)
protected
+ def starting_time
+ @starting_time ||= Time.now
+ end
+
def gemfile?
File.exist?("#{c.release_path}/Gemfile")
end
View
29 lib/engineyard-serverside/future.rb
@@ -1,29 +0,0 @@
-module EY
- module Serverside
- class Future
- def self.success?(futures)
- futures.empty? || futures.all? {|f| f.success?}
- end
-
- def initialize(server, *args, &block)
- @server = server
- @args = args
- @block = block
- end
-
- def success?
- @value == true
- end
-
- def error?
- !success?
- end
- end
-
- if defined?(Fiber)
- require 'engineyard-serverside/futures/celluloid'
- else
- require 'engineyard-serverside/futures/dataflow'
- end
- end
-end
View
25 lib/engineyard-serverside/futures/celluloid.rb
@@ -1,25 +0,0 @@
-module EY
- module Serverside
- $LOAD_PATH.unshift File.expand_path('../../vendor/celluloid/lib', File.dirname(__FILE__))
- require 'celluloid'
- class Future
- def self.call(servers, *args, &block)
- futures = servers.map do |server|
- new(server, *args, &block)
- end
-
- futures.each {|f| f.call}
- futures
- end
-
- def future
- Celluloid::Future.new(@server, *@args, &@block)
- end
-
- def call
- # Celluloid needs to call the block explicitely
- @value ||= future.call
- end
- end
- end
-end
View
31 lib/engineyard-serverside/futures/dataflow.rb
@@ -1,31 +0,0 @@
-module EY
- module Serverside
- $LOAD_PATH.unshift File.expand_path('../../vendor/dataflow', File.dirname(__FILE__))
- require 'dataflow'
-
- class Future
- extend Dataflow
-
- def self.call(servers, *args, &block)
- futures = []
- # Dataflow needs to call `barrier` and `need_later` in the same object
- barrier(*servers.map do |server|
- future = new(server, *args, &block)
- futures << future
-
- need_later { future.call }
- end)
-
- futures
- end
-
- def future
- @block.call(@server, *@args)
- end
-
- def call
- @value ||= future
- end
- end
- end
-end
View
8 lib/engineyard-serverside/lockfile_parser.rb
@@ -15,12 +15,16 @@ def initialize(lockfile_contents)
parse
end
+ def has_ey_config?
+ @contents.index(/^\s+ey_config\s\([^\)]+\)$/)
+ end
+
def any_database_adapter?
- any_ruby_adapter = %w[mysql2 mysql do_mysql pg do_postgres sqlite3].any? do |type|
+ any_ruby_adapter = %w[mysql2 mysql do_mysql pg do_postgres].any? do |type|
@contents.index(/^\s+#{type}\s\([^\)]+\)$/)
end
- any_jruby_adapter = %w[mysql postgresql sqlite3].any? do |type|
+ any_jruby_adapter = %w[mysql postgresql].any? do |type|
@contents.index(/^\s+jdbc-#{type}\s\([^\)]+\)$/) || @contents.index(/^\s+activerecord-jdbc#{type}-adapter\s\([^\)]+\)$/)
end
View
16 lib/engineyard-serverside/logged_output.rb
@@ -1,3 +1,5 @@
+require 'open4'
+
module EY
module Serverside
module LoggedOutput
@@ -40,18 +42,18 @@ def verbose?
end
def warning(msg)
- info "\nWARNING: #{msg}\n".gsub(/^/,'!> ')
+ info "WARNING: #{msg}\n".gsub(/^/,'!> ')
end
def info(msg)
with_logfile do |log|
- Tee.new($stdout, log) << (msg + "\n")
+ Tee.new($stdout, log) << ("#{with_timestamp(msg)}\n")
end
end
def debug(msg)
with_logfile do |log|
- log << "#{msg}\n"
+ log << "#{with_timestamp(msg)}\n"
end
end
@@ -60,7 +62,7 @@ def logged_system(cmd)
out = verbose? ? Tee.new($stdout, log) : log
err = Tee.new($stderr, log) # we always want to see errors
- out << ":: running #{cmd}\n"
+ out << with_timestamp(":: running #{cmd}\n")
# :quiet means don't raise an error on nonzero exit status
status = Open4.spawn cmd, 0 => '', 1 => out, 2 => err, :quiet => true
@@ -77,6 +79,12 @@ def logfile
EY::Serverside::LoggedOutput.logfile
end
+ def with_timestamp(msg)
+ return msg unless respond_to?(:starting_time)
+ time_passed = Time.now.to_i - starting_time.to_i
+ timestamp = "+%2dm %02ds " % time_passed.divmod(60)
+ msg.gsub(/^/, timestamp)
+ end
end
end
end
View
28 lib/engineyard-serverside/server.rb
@@ -83,36 +83,12 @@ def run(command)
if local?
logged_system(command)
else
- logged_system(ssh_command + Escape.shell_command(["#{user}@#{hostname}", command]))
+ logged_system(ssh_command + " " + Escape.shell_command(["#{user}@#{hostname}", command]))
end
end
- def copy(local_file, remote_file)
- logged_system(scp_command + Escape.shell_command([local_file, "#{user}@#{hostname}:#{remote_file}"]))
- end
-
def ssh_command
- "ssh #{ssh_options} "
- end
-
- def scp_command
- "scp #{ssh_options} "
- end
-
- def ssh_options
- "-i #{ENV['HOME']}/.ssh/internal -o StrictHostKeyChecking=no -o PasswordAuthentication=no"
- end
-
- def gem?(name, version)
- run("#{gem_command} list -i #{name} -v '#{version}'")
- end
-
- def install_gem(path)
- run("#{gem_command} install -q --no-ri --no-rdoc #{path}")
- end
-
- def gem_command
- File.expand_path('gem', Gem.default_bindir)
+ "ssh -i #{ENV['HOME']}/.ssh/internal -o StrictHostKeyChecking=no -o PasswordAuthentication=no"
end
end
View
22 lib/engineyard-serverside/task.rb
@@ -1,6 +1,7 @@
module EY
module Serverside
class Task
+ include Dataflow
attr_reader :config
alias :c :config
@@ -50,19 +51,18 @@ def sudo(cmd, &blk)
private
- def run_on_roles(cmd, wrapper=%w[sh -l -c], &block)
- servers = EY::Serverside::Server.from_roles(@roles)
- futures = EY::Serverside::Future.call(servers, block_given?) do |server, exec_block|
- to_run = exec_block ? block.call(server, cmd.dup) : cmd
- server.run(Escape.shell_command(wrapper + [to_run]))
+ def run_on_roles(cmd, wrapper=%w[sh -l -c])
+ results = EY::Serverside::Server.from_roles(@roles).map do |server|
+ to_run = block_given? ? yield(server, cmd.dup) : cmd
+ need_later { server.run(Escape.shell_command(wrapper + [to_run])) }
end
-
- unless EY::Serverside::Future.success?(futures)
- failures = futures.select {|f| f.error? }.map {|f| f.inspect}.join("\n")
- raise EY::Serverside::RemoteFailure.new(failures)
- end
- true
+ barrier *results
+ # MRI's truthiness check is an internal C thing that does not call
+ # any methods... so Dataflow cannot proxy it & we must "x == true"
+ # Rubinius, wherefore art thou!?
+ results.all?{|x| x == true } || raise(EY::Serverside::RemoteFailure.new(cmd))
end
+
end
end
end
View
2  lib/engineyard-serverside/version.rb
@@ -1,5 +1,5 @@
module EY
module Serverside
- VERSION = '1.5.23.pre'
+ VERSION = '1.5.26'
end
end
View
261 lib/vendor/celluloid/lib/celluloid.rb
@@ -1,261 +0,0 @@
-require 'logger'
-require 'thread'
-
-module Celluloid
- @logger = Logger.new STDERR
-
- class << self
- attr_accessor :logger # Thread-safe logger class
-
- def included(klass)
- klass.send :extend, ClassMethods
- end
-
- # Are we currently inside of an actor?
- def actor?
- !!Thread.current[:actor]
- end
-
- # Obtain the currently running actor (if one exists)
- def current_actor
- actor = Thread.current[:actor]
- raise NotActorError, "not in actor scope" unless actor
- actor.proxy
- end
- alias_method :current, :current_actor
-
- # Receive an asynchronous message
- def receive(timeout = nil, &block)
- actor = Thread.current[:actor]
- if actor
- actor.receive(timeout, &block)
- else
- Thread.mailbox.receive(timeout, &block)
- end
- end
-
- # Sleep letting the actor continue processing messages
- def sleep(interval)
- actor = Thread.current[:actor]
- if actor
- actor.sleep(interval)
- else
- Kernel.sleep interval
- end
- end
-
- # Obtain a hash of active tasks to their current activities
- def tasks
- actor = Thread.current[:actor]
- raise NotActorError, "not in actor scope" unless actor
- actor.tasks
- end
- end
-
- # Class methods added to classes which include Celluloid
- module ClassMethods
- # Create a new actor
- def new(*args, &block)
- proxy = Actor.new(allocate).proxy
- proxy.send(:initialize, *args, &block)
- proxy
- end
- alias_method :spawn, :new
-
- # Create a new actor and link to the current one
- def new_link(*args, &block)
- current_actor = Celluloid.current_actor
- raise NotActorError, "can't link outside actor context" unless current_actor
-
- proxy = Actor.new(allocate).proxy
- current_actor.link proxy
- proxy.send(:initialize, *args, &block)
- proxy
- end
- alias_method :spawn_link, :new_link
-
- # Create a supervisor which ensures an instance of an actor will restart
- # an actor if it fails
- def supervise(*args, &block)
- Supervisor.supervise(self, *args, &block)
- end
-
- # Create a supervisor which ensures an instance of an actor will restart
- # an actor if it fails, and keep the actor registered under a given name
- def supervise_as(name, *args, &block)
- Supervisor.supervise_as(name, self, *args, &block)
- end
-
- # Trap errors from actors we're linked to when they exit
- def trap_exit(callback)
- @exit_handler = callback.to_sym
- end
-
- # Obtain the exit handler for this actor
- attr_reader :exit_handler
-
- # Configure a custom mailbox factory
- def use_mailbox(klass = nil, &block)
- if block
- define_method(:mailbox_factory, &block)
- else
- define_method(:mailbox_factory) { klass.new }
- end
- end
- end
-
- #
- # Instance methods
- #
-
- # Is this actor alive?
- def alive?
- Thread.current[:actor].alive?
- end
-
- # Raise an exception in caller context, but stay running
- def abort(cause)
- raise AbortError.new(cause)
- end
-
- # Terminate this actor
- def terminate
- Thread.current[:actor].terminate
- end
-
- def inspect
- str = "#<Celluloid::Actor(#{self.class}:0x#{object_id.to_s(16)})"
- ivars = instance_variables.map do |ivar|
- "#{ivar}=#{instance_variable_get(ivar).inspect}"
- end
-
- str << " " << ivars.join(' ') unless ivars.empty?
- str << ">"
- end
-
- # Send a signal with the given name to all waiting methods
- def signal(name, value = nil)
- Thread.current[:actor].signal name, value
- end
-
- # Wait for the given signal
- def wait(name)
- Thread.current[:actor].wait name
- end
-
- # Obtain the current_actor
- def current_actor
- Celluloid.current_actor
- end
-
- # Obtain the running tasks for this actor
- def tasks
- Celluloid.tasks
- end
-
- # Obtain the Ruby object the actor is wrapping. This should ONLY be used
- # for a limited set of use cases like runtime metaprogramming. Interacting
- # directly with the wrapped object foregoes any kind of thread safety that
- # Celluloid would ordinarily provide you, and the object is guaranteed to
- # be shared with at least the actor thread. Tread carefully.
- def wrapped_object; self; end
-
- # Obtain the Celluloid::Links for this actor
- def links
- Thread.current[:actor].links
- end
-
- # Link this actor to another, allowing it to crash or react to errors
- def link(actor)
- actor.notify_link current_actor
- notify_link actor
- end
-
- # Remove links to another actor
- def unlink(actor)
- actor.notify_unlink current_actor
- notify_unlink actor
- end
-
- def notify_link(actor)
- links << actor
- end
-
- def notify_unlink(actor)
- links.delete actor
- end
-
- # Is this actor linked to another?
- def linked_to?(actor)
- Thread.current[:actor].links.include? actor
- end
-
- # Receive an asynchronous message via the actor protocol
- def receive(timeout = nil, &block)
- Celluloid.receive(timeout, &block)
- end
-
- # Sleep while letting the actor continue to receive messages
- def sleep(interval)
- Celluloid.sleep(interval)
- end
-
- # Call a block after a given interval
- def after(interval, &block)
- Thread.current[:actor].after(interval, &block)
- end
-
- # Perform a blocking or computationally intensive action inside an
- # asynchronous thread pool, allowing the caller to continue processing other
- # messages in its mailbox in the meantime
- def async(&block)
- # This implementation relies on the present implementation of
- # Celluloid::Future, which uses an Actor to run the block
- Future.new(&block).value
- end
-
- # Process async calls via method_missing
- def method_missing(meth, *args, &block)
- # bang methods are async calls
- if meth.to_s.match(/!$/)
- unbanged_meth = meth.to_s.sub(/!$/, '')
- call = AsyncCall.new(@mailbox, unbanged_meth, args, block)
-
- begin
- Thread.current[:actor].mailbox << call
- rescue MailboxError
- # Silently swallow asynchronous calls to dead actors. There's no way
- # to reliably generate DeadActorErrors for async calls, so users of
- # async calls should find other ways to deal with actors dying
- # during an async call (i.e. linking/supervisors)
- end
-
- return # casts are async and return immediately
- end
-
- super
- end
-end
-
-require 'celluloid/version'
-require 'celluloid/actor_proxy'
-require 'celluloid/calls'
-require 'celluloid/core_ext'
-require 'celluloid/events'
-require 'celluloid/fiber'
-require 'celluloid/fsm'
-require 'celluloid/links'
-require 'celluloid/logger'
-require 'celluloid/mailbox'
-require 'celluloid/receivers'
-require 'celluloid/registry'
-require 'celluloid/responses'
-require 'celluloid/signals'
-require 'celluloid/task'
-require 'celluloid/timers'
-
-require 'celluloid/actor'
-require 'celluloid/actor_pool'
-require 'celluloid/supervisor'
-require 'celluloid/future'
-require 'celluloid/application'
View
242 lib/vendor/celluloid/lib/celluloid/actor.rb
@@ -1,242 +0,0 @@
-module Celluloid
- # Don't do Actor-like things outside Actor scope
- class NotActorError < StandardError; end
-
- # Trying to do something to a dead actor
- class DeadActorError < StandardError; end
-
- # The caller made an error, not the current actor
- class AbortError < StandardError
- attr_reader :cause
-
- def initialize(cause)
- @cause = cause
- super "caused by #{cause.inspect}: #{cause.to_s}"
- end
- end
-
- # Actors are Celluloid's concurrency primitive. They're implemented as
- # normal Ruby objects wrapped in threads which communicate with asynchronous
- # messages.
- class Actor
- extend Registry
-
- attr_reader :proxy
- attr_reader :links
- attr_reader :mailbox
-
- # Invoke a method on the given actor via its mailbox
- def self.call(mailbox, meth, *args, &block)
- call = SyncCall.new(Thread.mailbox, meth, args, block)
-
- begin
- mailbox << call
- rescue MailboxError
- raise DeadActorError, "attempted to call a dead actor"
- end
-
- if Celluloid.actor?
- response = Thread.current[:actor].wait [:call, call.id]
- else
- # Otherwise we're inside a normal thread, so block
- response = Thread.mailbox.receive do |msg|
- msg.respond_to?(:call_id) and msg.call_id == call.id
- end
- end
-
- response.value
- end
-
- # Invoke a method asynchronously on an actor via its mailbox
- def self.async(mailbox, meth, *args, &block)
- begin
- mailbox << AsyncCall.new(Thread.mailbox, meth, args, block)
- rescue MailboxError
- # Silently swallow asynchronous calls to dead actors. There's no way
- # to reliably generate DeadActorErrors for async calls, so users of
- # async calls should find other ways to deal with actors dying
- # during an async call (i.e. linking/supervisors)
- end
- end
-
- # Wrap the given subject with an Actor
- def initialize(subject)
- @subject = subject
-
- if subject.respond_to? :mailbox_factory
- @mailbox = subject.mailbox_factory
- else
- @mailbox = Mailbox.new
- end
-
- @links = Links.new
- @signals = Signals.new
- @receivers = Receivers.new
- @timers = Timers.new
- @proxy = ActorProxy.new(@mailbox, self.class.to_s)
- @running = true
-
- @thread = Pool.get do
- Thread.current[:actor] = self
- Thread.current[:mailbox] = @mailbox
-
- run
- end
- end
-
- # Is this actor alive?
- def alive?
- @running
- end
-
- # Terminate this actor
- def terminate
- @running = false
- nil
- end
-
- # Send a signal with the given name to all waiting methods
- def signal(name, value = nil)
- @signals.send name, value
- end
-
- # Wait for the given signal
- def wait(name)
- @signals.wait name
- end
-
- # Receive an asynchronous message
- def receive(timeout = nil, &block)
- @receivers.receive(timeout, &block)
- end
-
- # Run the actor loop
- def run
- while @running
- begin
- message = @mailbox.receive(timeout)
- rescue ExitEvent => exit_event
- Task.new(:exit_handler) { handle_exit_event exit_event }.resume
- retry
- end
-
- if message
- handle_message message
- else
- # No message indicates a timeout
- @timers.fire
- @receivers.fire_timers
- end
- end
-
- cleanup ExitEvent.new(@proxy)
- rescue MailboxShutdown
- # If the mailbox detects shutdown, exit the actor
- @running = false
- rescue Exception => ex
- @running = false
- handle_crash(ex)
- ensure
- Pool.put @thread
- end
-
- # How long to wait until the next timer fires
- def timeout
- i1 = @timers.wait_interval
- i2 = @receivers.wait_interval
-
- if i1 and i2
- i1 < i2 ? i1 : i2
- elsif i1
- i1
- else
- i2
- end
- end
-
- # Obtain a hash of tasks that are currently waiting
- def tasks
- # A hash of tasks to what they're waiting on is more meaningful to the
- # end-user, and lets us make a copy of the tasks table, rather than
- # handing them the one we're using internally across threads, a definite
- # thread safety shared state no-no
- tasks = {}
- current_task = Task.current rescue nil
- tasks[current_task] = :running if current_task
-
- @signals.waiting.each do |waitable, waiters|
- if waiters.is_a? Enumerable
- waiters.each { |waiter| tasks[waiter] = waitable }
- else
- tasks[waiters] = waitable
- end
- end
-
- tasks
- end
-
- # Schedule a block to run at the given time
- def after(interval)
- @timers.add(interval) do
- Task.new(:timer) { yield }.resume
- end
- end
-
- # Sleep for the given amount of time
- def sleep(interval)
- task = Task.current
- @timers.add(interval) { task.resume }
- Task.suspend
- end
-
- # Handle an incoming message
- def handle_message(message)
- case message
- when Call
- Task.new(:message_handler) { message.dispatch(@subject) }.resume
- when Response
- handled_successfully = signal [:call, message.call_id], message
-
- unless handled_successfully
- Logger.debug("anomalous message! spurious response to call #{message.call_id}")
- end
- else
- @receivers.handle_message(message)
- end
- message
- end
-
- # Handle exit events received by this actor
- def handle_exit_event(exit_event)
- exit_handler = @subject.class.exit_handler
- if exit_handler
- return @subject.send(exit_handler, exit_event.actor, exit_event.reason)
- end
-
- # Reraise exceptions from linked actors
- # If no reason is given, actor terminated cleanly
- raise exit_event.reason if exit_event.reason
- end
-
- # Handle any exceptions that occur within a running actor
- def handle_crash(exception)
- Logger.crash("#{@subject.class} crashed!", exception)
- cleanup ExitEvent.new(@proxy, exception)
- rescue Exception => ex
- Logger.crash("#{@subject.class}: ERROR HANDLER CRASHED!", ex)
- end
-
- # Handle cleaning up this actor after it exits
- def cleanup(exit_event)
- @mailbox.shutdown
- @links.send_event exit_event
- tasks.each { |task, _| task.terminate }
-
- begin
- @subject.finalize if @subject.respond_to? :finalize
- rescue Exception => ex
- Logger.crash("#{@subject.class}#finalize crashed!", ex)
- end
- end
- end
-end
View
54 lib/vendor/celluloid/lib/celluloid/actor_pool.rb
@@ -1,54 +0,0 @@
-require 'thread'
-
-module Celluloid
- class Actor
- # Maintain a thread pool of actors FOR SPEED!!
- class Pool
- @pool = []
- @lock = Mutex.new
- @max_idle = 16
-
- class << self
- attr_accessor :max_idle
-
- def get(&block)
- @lock.synchronize do
- if @pool.empty?
- thread = create
- else
- thread = @pool.shift
- end
-
- thread[:queue] << block
- thread
- end
- end
-
- def put(thread)
- @lock.synchronize do
- if @pool.size >= @max_idle
- thread[:queue] << nil
- else
- @pool << thread
- end
- end
- end
-
- def create
- queue = Queue.new
- thread = Thread.new do
- begin
- while func = queue.pop
- func.call
- end
- rescue Exception => ex
- Logger.crash("#{self} internal failure", ex)
- end
- end
- thread[:queue] = queue
- thread
- end
- end
- end
- end
-end
View
75 lib/vendor/celluloid/lib/celluloid/actor_proxy.rb
@@ -1,75 +0,0 @@
-module Celluloid
- # A proxy object returned from Celluloid::Actor.spawn/spawn_link which
- # dispatches calls and casts to normal Ruby objects which are running inside
- # of their own threads.
- class ActorProxy
- attr_reader :mailbox
-
- def initialize(mailbox, klass = "Object")
- @mailbox, @klass = mailbox, klass
- end
-
- def send(meth, *args, &block)
- Actor.call @mailbox, :send, meth, *args, &block
- end
-
- def class
- Actor.call @mailbox, :send, :class
- end
-
- def respond_to?(meth)
- Actor.call @mailbox, :respond_to?, meth
- end
-
- def methods(include_ancestors = true)
- Actor.call @mailbox, :methods, include_ancestors
- end
-
- def alive?
- @mailbox.alive?
- end
-
- def to_s
- Actor.call @mailbox, :to_s
- end
-
- def inspect
- Actor.call @mailbox, :inspect
- rescue DeadActorError
- "#<Celluloid::Actor(#{@klass}) dead>"
- end
-
- # Create a Celluloid::Future which calls a given method
- def future(method_name, *args, &block)
- Future.new { Actor.call @mailbox, method_name, *args, &block }
- end
-
- # Terminate the associated actor
- def terminate
- raise DeadActorError, "actor already terminated" unless alive?
-
- begin
- send :terminate
- rescue DeadActorError
- # In certain cases this is thrown during termination. This is likely
- # a bug in Celluloid's internals, but it shouldn't affect the caller.
- # FIXME: track this down and fix it, or at the very least log it
- end
-
- # Always return nil until a dependable exit value can be obtained
- nil
- end
-
- # method_missing black magic to call bang predicate methods asynchronously
- def method_missing(meth, *args, &block)
- # bang methods are async calls
- if meth.to_s.match(/!$/)
- unbanged_meth = meth.to_s.sub(/!$/, '')
- Actor.async @mailbox, unbanged_meth, *args, &block
- return
- end
-
- Actor.call @mailbox, meth, *args, &block
- end
- end
-end
View
78 lib/vendor/celluloid/lib/celluloid/application.rb
@@ -1,78 +0,0 @@
-module Celluloid
- # Applications describe and manage networks of Celluloid actors
- class Application
- include Celluloid
- trap_exit :restart_supervisor
-
- class << self
- # Actors or sub-applications to be supervised
- def supervisables
- @supervisables ||= []
- end
-
- # Start this application (and watch it with a supervisor)
- alias_method :run!, :supervise
-
- # Run the application in the foreground with a simple watchdog
- def run
- loop do
- supervisor = run!
-
- # Take five, toplevel supervisor
- sleep 5 while supervisor.alive?
-
- Logger.error "!!! Celluloid::Application #{self} crashed. Restarting..."
- end
- end
-
- # Register an actor class or a sub-application class to be launched and
- # supervised while this application is running. Available options are:
- #
- # * as: register this application in the Celluloid::Actor[] directory
- # * args: start the actor with the given arguments
- def supervise(klass, options = {})
- supervisables << Supervisable.new(klass, options)
- end
- end
-
- # Start the application
- def initialize
- @supervisors = {}
-
- # This is some serious lolcode, but like... start the supervisors for
- # this application
- self.class.supervisables.each do |supervisable|
- supervisor = supervisable.supervise
- @supervisors[supervisor] = supervisable
- end
- end
-
- # Restart a crashed supervisor
- def restart_supervisor(supervisor, reason)
- supervisable = @supervisors.delete supervisor
- raise "a supervisable went missing. This shouldn't be!" unless supervisable
-
- supervisor = supervisable.supervise
- @supervisors[supervisor] = supervisable
- end
-
- # A subcomponent of an application to be supervised
- class Supervisable
- attr_reader :klass, :as, :args
-
- def initialize(klass, options = {})
- @klass = klass
-
- # Stringify keys :/
- options = options.inject({}) { |h,(k,v)| h[k.to_s] = v; h }
-
- @as = options['as']
- @args = options['args'] || []
- end
-
- def supervise
- Supervisor.new_link(@as, @klass, *@args)
- end
- end
- end
-end
View
94 lib/vendor/celluloid/lib/celluloid/calls.rb
@@ -1,94 +0,0 @@
-module Celluloid
- # Calls represent requests to an actor
- class Call
- attr_reader :id, :caller, :method, :arguments, :block
-
- def initialize(caller, method, arguments, block)
- @id = object_id # memoize object ID for serialization
- @caller, @method, @arguments, @block = caller, method, arguments, block
- end
-
- def check_signature(obj)
- unless obj.respond_to? @method
- raise NoMethodError, "undefined method `#{@method}' for #{obj.inspect}"
- end
-
- arity = obj.method(@method).arity
- if arity >= 0
- if arguments.size != arity
- raise ArgumentError, "wrong number of arguments (#{arguments.size} for #{arity})"
- end
- elsif arity < -1
- mandatory_args = -arity - 1
- if arguments.size < mandatory_args
- raise ArgumentError, "wrong number of arguments (#{arguments.size} for #{mandatory_args})"
- end
- end
- end
- end
-
- # Synchronous calls wait for a response
- class SyncCall < Call
- def dispatch(obj)
- begin
- check_signature(obj)
- rescue Exception => ex
- respond ErrorResponse.new(@id, AbortError.new(ex))
- return
- end
-
- begin
- result = obj.send @method, *@arguments, &@block
- rescue Exception => exception
- # Exceptions that occur during synchronous calls are reraised in the
- # context of the caller
- respond ErrorResponse.new(@id, exception)
-
- if exception.is_a? AbortError
- # Aborting indicates a protocol error on the part of the caller
- # It should crash the caller, but the exception isn't reraised
- return
- else
- # Otherwise, it's a bug in this actor and should be reraised
- raise exception
- end
- end
-
- respond SuccessResponse.new(@id, result)
- end
-
- def cleanup
- exception = DeadActorError.new("attempted to call a dead actor")
- respond ErrorResponse.new(@id, exception)
- end
-
- #######
- private
- #######
-
- def respond(message)
- @caller << message
- rescue MailboxError
- # It's possible the caller exited or crashed before we could send a
- # response to them.
- end
- end
-
- # Asynchronous calls don't wait for a response
- class AsyncCall < Call
- def dispatch(obj)
- begin
- check_signature(obj)
- rescue Exception => ex
- Logger.crash("#{obj.class}: async call failed!", ex)
- return
- end
-
- obj.send(@method, *@arguments, &@block)
- rescue AbortError => ex
- # Swallow aborted async calls, as they indicate the caller made a mistake
- Logger.crash("#{obj.class}: async call aborted!", ex)
- end
- end
-end
-
View
14 lib/vendor/celluloid/lib/celluloid/core_ext.rb
@@ -1,14 +0,0 @@
-require 'celluloid/fiber'
-
-# Monkeypatch Thread to allow lazy access to its Celluloid::Mailbox
-class Thread
- # Retrieve the mailbox for the current thread or lazily initialize it
- def self.mailbox
- current[:mailbox] ||= Celluloid::Mailbox.new
- end
-end
-
-class Fiber
- # Celluloid::Task associated with this Fiber
- attr_accessor :task
-end
View
14 lib/vendor/celluloid/lib/celluloid/events.rb
@@ -1,14 +0,0 @@
-module Celluloid
- # Exceptional system events which need to be processed out of band
- class SystemEvent < Exception; end
-
- # An actor has exited for the given reason
- class ExitEvent < SystemEvent
- attr_reader :actor, :reason
-
- def initialize(actor, reason = nil)
- @actor, @reason = actor, reason
- super reason.to_s
- end
- end
-end
View
33 lib/vendor/celluloid/lib/celluloid/fiber.rb
@@ -1,33 +0,0 @@
-# Fibers are hard... let's go shopping!
-begin
- require 'fiber'
-rescue LoadError => ex
- if defined? JRUBY_VERSION
- if RUBY_VERSION < "1.9.2"
- raise LoadError, "Celluloid requires JRuby 1.9 mode. Please pass the --1.9 flag or set JRUBY_OPTS=--1.9"
- end
-
- # Fibers are broken on JRuby 1.6.5. This works around the issue
- if JRUBY_VERSION == "1.6.5"
- require 'jruby'
- org.jruby.ext.fiber.FiberExtLibrary.new.load(JRuby.runtime, false)
- class org::jruby::ext::fiber::ThreadFiber
- field_accessor :state
- end
-
- class Fiber
- def alive?
- JRuby.reference(self).state != org.jruby.ext.fiber.ThreadFiberState::FINISHED
- end
- end
- else
- # Just in case subsequent JRuby releases have broken fibers :/
- raise ex
- end
- elsif defined? Rubinius
- # If we're on Rubinius, we can still work in 1.8 mode
- Fiber = Rubinius::Fiber
- else
- raise ex
- end
-end
View
141 lib/vendor/celluloid/lib/celluloid/fsm.rb
@@ -1,141 +0,0 @@
-module Celluloid
- # Turn concurrent objects into finite state machines
- # Inspired by Erlang's gen_fsm. See http://www.erlang.org/doc/man/gen_fsm.html
- module FSM
- DEFAULT_STATE = :default # Default state name unless one is explicitly set
-
- # Included hook to extend class methods
- def self.included(klass)
- klass.send :include, Celluloid
- klass.send :extend, ClassMethods
- end
-
- module ClassMethods
- # Ensure FSMs transition into the default state after they're initialized
- def new(*args, &block)
- fsm = super
- fsm.transition default_state
- fsm
- end
-
- # Ensure FSMs transition into the default state after they're initialized
- def new_link(*args, &block)
- fsm = super
- fsm.transition default_state
- fsm
- end
-
- # Obtain or set the default state
- # Passing a state name sets the default state
- def default_state(new_default = nil)
- if new_default
- @default_state = new_default.to_sym
- else
- defined?(@default_state) ? @default_state : DEFAULT_STATE
- end
- end
-
- # Obtain the valid states for this FSM
- def states
- @states ||= {}
- end
-
- # Declare an FSM state and optionally provide a callback block to fire
- # Options:
- # * to: a state or array of states this state can transition to
- def state(*args, &block)
- if args.last.is_a? Hash
- options = args.pop.inject({}) { |h,(k,v)| h[k.to_s] = v; h }
- else
- options = {}
- end
-
- args.each do |name|
- name = name.to_sym
- states[name] = State.new(name, options['to'], &block)
- end
- end
- end
-
- # Obtain the current state of the FSM
- def current_state
- defined?(@state) ? @state : @state = self.class.default_state
- end
- alias_method :state, :current_state
-
- # Transition to another state
- # Options:
- # * delay: don't transition immediately, wait the given number of seconds.
- # This will return a Celluloid::Timer object you can use to
- # cancel the pending state transition.
- #
- # Note: making additional state transitions will cancel delayed transitions
- def transition(state_name, options = {})
- state_name = state_name.to_sym
- current_state = self.class.states[@state]
-
- return if current_state && current_state.name == state_name
-
- if current_state and not current_state.valid_transition? state_name
- valid = current_state.transitions.map(&:to_s).join(", ")
- raise ArgumentError, "#{self.class} can't change state from '#{@state}' to '#{state_name}', only to: #{valid}"
- end
-
- new_state = self.class.states[state_name]
-
- if !new_state and state_name == self.class.default_state
- # FIXME This probably isn't thread safe... or wise
- new_state = self.class.states[state_name] = State.new(state_name)
- end
-
- if new_state
- if options[:delay]
- @delayed_transition.cancel if @delayed_transition
-
- @delayed_transition = after(options[:delay]) do
- transition! new_state.name
- new_state.call(self)
- end
-
- return @delayed_transition
- end
-
- if defined?(@delayed_transition) and @delayed_transition
- @delayed_transition.cancel
- @delayed_transition = nil
- end
-
- transition! new_state.name
- new_state.call(self)
- else
- raise ArgumentError, "invalid state for #{self.class}: #{state_name}"
- end
- end
-
- # Immediate state transition with no sanity checks. "Dangerous!"
- def transition!(state_name)
- @state = state_name
- end
-
- # FSM states as declared by Celluloid::FSM.state
- class State
- attr_reader :name, :transitions
-
- def initialize(name, transitions = nil, &block)
- @name, @block = name, block
- @transitions = Array(transitions).map { |t| t.to_sym } if transitions
- end
-
- def call(obj)
- obj.instance_eval(&@block) if @block
- end
-
- def valid_transition?(new_state)
- # All transitions are allowed unless expressly
- return true unless @transitions
-
- @transitions.include? new_state.to_sym
- end
- end
- end
-end
View
60 lib/vendor/celluloid/lib/celluloid/future.rb
@@ -1,60 +0,0 @@
-require 'thread'
-
-module Celluloid
- # Celluloid::Future objects allow methods and blocks to run in the
- # background, their values requested later
- class Future
- # Create a new Celluloid::Future object, allowing a block to be computed in
- # the background and its return value obtained later
- def initialize(*args, &block)
- @lock = Mutex.new
- @value_obtained = false
-
- @runner = Runner.new(*args, &block)
- @runner.run!
- end
-
- # Obtain the value for this Future
- def value
- @lock.synchronize do
- unless @value_obtained
- @value = @runner.value
- @runner.terminate
- @value_obtained = true
- end
-
- @value
- end
- end
- alias_method :call, :value
-
- # Inspect this Celluloid::Future
- alias_method :inspect, :to_s
-
- # Runner is an internal class which executes the given block/method
- class Runner
- include Celluloid
-
- def initialize(*args, &block)
- @args, @block = args, block
- @called = nil
- @error = nil
- end
-
- def run
- @value = @block.call(*@args)
- rescue Exception => error
- @error = error
- ensure
- @called = true
- signal :finished
- end
-
- def value
- wait :finished unless @called
- abort @error if @error
- @value
- end
- end
- end
-end
View
61 lib/vendor/celluloid/lib/celluloid/links.rb
@@ -1,61 +0,0 @@
-require 'thread'
-
-module Celluloid
- # Thread safe storage of inter-actor links
- class Links
- include Enumerable
-
- def initialize
- @links = {}
- @lock = Mutex.new
- end
-
- # Add an actor to the current links
- def <<(actor)
- @lock.synchronize do
- @links[actor.mailbox.address] = actor
- end
- actor
- end
-
- # Do links include the given actor?
- def include?(actor)
- @lock.synchronize do
- @links.has_key? actor.mailbox.address
- end
- end
-
- # Remove an actor from the links
- def delete(actor)
- @lock.synchronize do
- @links.delete actor.mailbox.address
- end
- actor
- end
-
- # Iterate through all links
- def each
- @lock.synchronize do
- @links.each { |_, actor| yield(actor) }
- end
- end
-
- # Map across links
- def map
- result = []
- each { |actor| result << yield(actor) }
- result
- end
-
- # Send an event message to all actors
- def send_event(event)
- each { |actor| actor.mailbox.system_event event }
- end
-
- # Generate a string representation
- def inspect
- links = self.map(&:inspect).join(',')
- "#<#{self.class}[#{links}]>"
- end
- end
-end
View
32 lib/vendor/celluloid/lib/celluloid/logger.rb
@@ -1,32 +0,0 @@
-module Celluloid
- module Logger
- module_function
-
- # Send a debug message
- def debug(string)
- Celluloid.logger.debug(string) if Celluloid.logger
- end
-
- # Send a info message
- def info(string)
- Celluloid.logger.info(string) if Celluloid.logger
- end
-
- # Send a warning message
- def warn(string)
- Celluloid.logger.warn(string) if Celluloid.logger
- end
-
- # Send an error message
- def error(string)
- Celluloid.logger.error(string) if Celluloid.logger
- end
-
- # Handle a crash
- def crash(string, exception)
- string += "\n#{exception.class}: #{exception.to_s}\n"
- string << exception.backtrace.join("\n")
- error(string)
- end
- end
-end
View
124 lib/vendor/celluloid/lib/celluloid/mailbox.rb
@@ -1,124 +0,0 @@
-require 'thread'
-
-module Celluloid
- class MailboxError < StandardError; end # you can't message the dead
- class MailboxShutdown < StandardError; end # raised if the mailbox can no longer be used
-
- # Actors communicate with asynchronous messages. Messages are buffered in
- # Mailboxes until Actors can act upon them.
- class Mailbox
- include Enumerable
-
- # A unique address at which this mailbox can be found
- alias_method :address, :object_id
-
- def initialize
- @messages = []
- @lock = Mutex.new
- @dead = false
- @condition = ConditionVariable.new
- end
-
- # Add a message to the Mailbox
- def <<(message)
- @lock.synchronize do
- raise MailboxError, "dead recipient" if @dead
-
- @messages << message
- @condition.signal
- end
- nil
- end
-
- # Add a high-priority system event to the Mailbox
- def system_event(event)
- @lock.synchronize do
- unless @dead # Silently fail if messages are sent to dead actors
- @messages.unshift event
- @condition.signal
- end
- end
- nil
- end
-
- # Receive a message from the Mailbox
- def receive(timeout = nil, &block)
- message = nil
-
- @lock.synchronize do
- raise MailboxError, "attempted to receive from a dead mailbox" if @dead
-
- begin
- message = next_message(&block)
-
- unless message
- if timeout
- now = Time.now
- wait_until ||= now + timeout
- wait_interval = wait_until - now
- return if wait_interval < 0
- else
- wait_interval = nil
- end
-
- @condition.wait(@lock, wait_interval)
- end
- end until message
- end
-
- message
- end
-
- # Retrieve the next message in the mailbox
- def next_message
- message = nil
-
- if block_given?
- index = @messages.index do |msg|
- yield(msg) || msg.is_a?(SystemEvent)
- end
-
- message = @messages.slice!(index, 1).first if index
- else
- message = @messages.shift
- end
-
- raise message if message.is_a? SystemEvent
- message
- end
-
- # Shut down this mailbox and clean up its contents
- def shutdown
- messages = nil
-
- @lock.synchronize do
- messages = @messages
- @messages = []
- @dead = true
- end
-
- messages.each { |msg| msg.cleanup if msg.respond_to? :cleanup }
- true
- end
-
- # Is the mailbox alive?
- def alive?
- !@dead
- end
-
- # Cast to an array
- def to_a
- @lock.synchronize { @messages.dup }
- end
-
- # Iterate through the mailbox
- def each(&block)
- to_a.each(&block)
- end
-
- # Inspect the contents of the Mailbox
- def inspect
- "#<#{self.class}:#{object_id.to_s(16)} @messages=[#{map { |m| m.inspect }.join(', ')}]>"
- end
- end
-end
View
66 lib/vendor/celluloid/lib/celluloid/receivers.rb
@@ -1,66 +0,0 @@
-require 'set'
-
-module Celluloid
- # Allow methods to directly interact with the actor protocol
- class Receivers
- def initialize
- @receivers = Set.new
- @timers = Timers.new
- end
-
- # Receive an asynchronous message
- def receive(timeout = nil, &block)
- receiver = Receiver.new block
-
- if timeout
- receiver.timer = @timers.add(timeout) do
- @receivers.delete receiver
- receiver.resume
- end
- end
-
- @receivers << receiver
- Task.suspend
- end
-
- # How long to wait until the next timer fires
- def wait_interval
- @timers.wait_interval
- end
-
- # Fire any pending timers
- def fire_timers
- @timers.fire
- end
-
- # Handle incoming messages
- def handle_message(message)
- receiver = @receivers.find { |r| r.match(message) }
- return unless receiver
-
- @receivers.delete receiver
- @timers.cancel receiver.timer if receiver.timer
- receiver.resume message
- end
- end
-
- # Methods blocking on a call to receive
- class Receiver
- attr_accessor :timer
-
- def initialize(block)
- @block = block
- @task = Task.current
- @timer = nil
- end
-
- # Match a message with this receiver's block
- def match(message)
- @block.call(message) if @block
- end
-
- def resume(message = nil)
- @task.resume message
- end
- end
-end
View
33 lib/vendor/celluloid/lib/celluloid/registry.rb
@@ -1,33 +0,0 @@
-require 'thread'
-
-module Celluloid
- # The Registry allows us to refer to specific actors by human-meaningful names
- module Registry
- @@registry = {}
- @@registry_lock = Mutex.new
-
- # Register an Actor
- def []=(name, actor)
- actor_singleton = class << actor; self; end
- unless actor_singleton.ancestors.include? ActorProxy
- raise TypeError, "not an actor"
- end
-
- @@registry_lock.synchronize do
- @@registry[name.to_sym] = actor
- end
- end
-
- # Retrieve an actor by name
- def [](name)
- @@registry_lock.synchronize do
- @@registry[name.to_sym]
- end
- end
-
- # List all registered actors by name
- def registered
- @@registry_lock.synchronize { @@registry.keys }
- end
- end
-end
View
26 lib/vendor/celluloid/lib/celluloid/responses.rb
@@ -1,26 +0,0 @@
-module Celluloid
- # Responses to calls
- class Response
- attr_reader :call_id, :value
-
- def initialize(call_id, value)
- @call_id, @value = call_id, value
- end
- end
-
- # Call completed successfully
- class SuccessResponse < Response; end
-
- # Call was aborted due to caller error
- class ErrorResponse < Response
- def value
- if super.is_a? AbortError
- # Aborts are caused by caller error, so ensure they capture the
- # caller's backtrace instead of the receiver's
- raise super.cause.class.new(super.cause.message)
- else
- raise super
- end
- end
- end
-end
View
2  lib/vendor/celluloid/lib/celluloid/rspec.rb
@@ -1,2 +0,0 @@
-require File.expand_path('../../../spec/support/actor_examples', __FILE__)
-require File.expand_path('../../../spec/support/mailbox_examples', __FILE__)
View
50 lib/vendor/celluloid/lib/celluloid/signals.rb
@@ -1,50 +0,0 @@
-module Celluloid
- # Event signaling between methods of the same object
- class Signals
- attr_reader :waiting
-
- def initialize
- @waiting = {}
- end
-
- # Wait for the given signal and return the associated value
- def wait(signal)
- tasks = @waiting[signal]
-
- case tasks
- when Array
- tasks << Task.current
- when NilClass
- @waiting[signal] = Task.current
- else
- @waiting[signal] = [tasks, Task.current]
- end
-
- Task.suspend
- end
-
- # Send a signal to all method calls waiting for the given name
- # Returns true if any calls were signaled, or false otherwise
- def send(name, value = nil)
- tasks = @waiting.delete name
-
- case tasks
- when Array
- tasks.each { |task| run_task task, value }
- when NilClass
- Logger.debug("spurious signal: #{name}")
- else
- run_task tasks, value
- end
-
- value
- end
-
- # Run the given task, reporting errors that occur
- def run_task(task, value)
- task.resume(value)
- rescue => ex
- Celluloid::Logger.crash("signaling error", ex)
- end
- end
-end
View
57 lib/vendor/celluloid/lib/celluloid/supervisor.rb
@@ -1,57 +0,0 @@
-module Celluloid
- # Supervisors are actors that watch over other actors and restart them if
- # they crash
- class Supervisor
- include Celluloid
- trap_exit :restart_actor
-
- # Retrieve the actor this supervisor is supervising
- attr_reader :actor
-
- def self.supervise(klass, *args, &block)
- new(nil, klass, *args, &block)
- end
-
- def self.supervise_as(name, klass, *args, &block)
- new(name, klass, *args, &block)
- end
-
- def initialize(name, klass