creeper 1.0.9 → 2.0.0
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/.gitignore +1 -0
- data/.rvmrc +48 -0
- data/Gemfile +17 -1
- data/Guardfile +32 -0
- data/Rakefile +9 -1
- data/bin/creeper +10 -58
- data/bin/creeperctl +74 -0
- data/config.ru +18 -0
- data/creeper.gemspec +19 -9
- data/lib/creeper.rb +108 -413
- data/lib/creeper/beanstalk_connection.rb +35 -0
- data/lib/creeper/cli.rb +225 -0
- data/lib/creeper/client.rb +93 -0
- data/lib/creeper/core_ext.rb +54 -0
- data/lib/creeper/exception_handler.rb +30 -0
- data/lib/creeper/extensions/action_mailer.rb +33 -0
- data/lib/creeper/extensions/active_record.rb +30 -0
- data/lib/creeper/extensions/generic_proxy.rb +26 -0
- data/lib/creeper/fetch.rb +94 -0
- data/lib/creeper/legacy.rb +46 -0
- data/lib/creeper/logging.rb +46 -0
- data/lib/creeper/manager.rb +164 -0
- data/lib/creeper/middleware/chain.rb +100 -0
- data/lib/creeper/middleware/server/active_record.rb +13 -0
- data/lib/creeper/middleware/server/logging.rb +31 -0
- data/lib/creeper/middleware/server/retry_jobs.rb +79 -0
- data/lib/creeper/middleware/server/timeout.rb +21 -0
- data/lib/creeper/paginator.rb +31 -0
- data/lib/creeper/processor.rb +116 -0
- data/lib/creeper/rails.rb +21 -0
- data/lib/creeper/redis_connection.rb +28 -0
- data/lib/creeper/testing.rb +44 -0
- data/lib/creeper/util.rb +45 -0
- data/lib/creeper/version.rb +1 -1
- data/lib/creeper/web.rb +248 -0
- data/lib/creeper/worker.rb +62 -313
- data/spec/dummy/.gitignore +15 -0
- data/spec/dummy/Gemfile +51 -0
- data/spec/dummy/README.rdoc +261 -0
- data/spec/dummy/Rakefile +7 -0
- data/spec/dummy/app/assets/images/rails.png +0 -0
- data/spec/dummy/app/assets/javascripts/application.js +15 -0
- data/spec/dummy/app/assets/stylesheets/application.css +13 -0
- data/spec/dummy/app/controllers/application_controller.rb +3 -0
- data/spec/dummy/app/controllers/work_controller.rb +71 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/mailers/.gitkeep +0 -0
- data/spec/dummy/app/mailers/user_mailer.rb +9 -0
- data/spec/dummy/app/models/.gitkeep +0 -0
- data/spec/dummy/app/models/post.rb +8 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/app/views/user_mailer/greetings.html.erb +3 -0
- data/spec/dummy/app/views/work/index.html.erb +1 -0
- data/spec/dummy/app/workers/fast_worker.rb +10 -0
- data/spec/dummy/app/workers/hard_worker.rb +11 -0
- data/spec/dummy/app/workers/lazy_worker.rb +12 -0
- data/spec/dummy/app/workers/suicidal_worker.rb +33 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/config/application.rb +68 -0
- data/spec/dummy/config/boot.rb +6 -0
- data/spec/dummy/config/creeper.yml +9 -0
- data/spec/dummy/config/database.yml +25 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +37 -0
- data/spec/dummy/config/environments/production.rb +67 -0
- data/spec/dummy/config/environments/test.rb +37 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/creeper.rb +8 -0
- data/spec/dummy/config/initializers/inflections.rb +15 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +7 -0
- data/spec/dummy/config/initializers/session_store.rb +8 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +5 -0
- data/spec/dummy/config/routes.rb +13 -0
- data/spec/dummy/db/migrate/20120123214055_create_posts.rb +10 -0
- data/spec/dummy/db/schema.rb +23 -0
- data/spec/dummy/db/seeds.rb +7 -0
- data/spec/dummy/lib/assets/.gitkeep +0 -0
- data/spec/dummy/lib/tasks/.gitkeep +0 -0
- data/spec/dummy/log/.gitkeep +0 -0
- data/spec/dummy/public/404.html +26 -0
- data/spec/dummy/public/422.html +26 -0
- data/spec/dummy/public/500.html +25 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/public/index.html +241 -0
- data/spec/dummy/public/robots.txt +5 -0
- data/spec/dummy/script/rails +6 -0
- data/spec/dummy/vendor/assets/javascripts/.gitkeep +0 -0
- data/spec/dummy/vendor/assets/stylesheets/.gitkeep +0 -0
- data/spec/dummy/vendor/plugins/.gitkeep +0 -0
- data/spec/lib/creeper/cli_spec.rb +208 -0
- data/spec/lib/creeper/client_spec.rb +110 -0
- data/spec/lib/creeper/exception_handler_spec.rb +110 -0
- data/spec/lib/creeper/processor_spec.rb +92 -0
- data/spec/lib/creeper/testing_spec.rb +105 -0
- data/spec/lib/creeper_spec.rb +54 -120
- data/spec/spec_helper.rb +81 -7
- data/spec/support/config.yml +9 -0
- data/spec/support/fake_env.rb +0 -0
- data/spec/support/workers/base_worker.rb +11 -0
- data/spec/support/workers/my_worker.rb +4 -0
- data/spec/support/workers/queued_worker.rb +5 -0
- data/spec/support/workers/real_worker.rb +10 -0
- data/web/assets/images/bootstrap/glyphicons-halflings-white.png +0 -0
- data/web/assets/images/bootstrap/glyphicons-halflings.png +0 -0
- data/web/assets/javascripts/application.js +49 -0
- data/web/assets/javascripts/vendor/bootstrap.js +12 -0
- data/web/assets/javascripts/vendor/bootstrap/bootstrap-alert.js +91 -0
- data/web/assets/javascripts/vendor/bootstrap/bootstrap-button.js +98 -0
- data/web/assets/javascripts/vendor/bootstrap/bootstrap-carousel.js +154 -0
- data/web/assets/javascripts/vendor/bootstrap/bootstrap-collapse.js +136 -0
- data/web/assets/javascripts/vendor/bootstrap/bootstrap-dropdown.js +92 -0
- data/web/assets/javascripts/vendor/bootstrap/bootstrap-modal.js +210 -0
- data/web/assets/javascripts/vendor/bootstrap/bootstrap-popover.js +95 -0
- data/web/assets/javascripts/vendor/bootstrap/bootstrap-scrollspy.js +125 -0
- data/web/assets/javascripts/vendor/bootstrap/bootstrap-tab.js +130 -0
- data/web/assets/javascripts/vendor/bootstrap/bootstrap-tooltip.js +270 -0
- data/web/assets/javascripts/vendor/bootstrap/bootstrap-transition.js +51 -0
- data/web/assets/javascripts/vendor/bootstrap/bootstrap-typeahead.js +271 -0
- data/web/assets/javascripts/vendor/jquery.js +9266 -0
- data/web/assets/javascripts/vendor/jquery.timeago.js +148 -0
- data/web/assets/stylesheets/application.css +6 -0
- data/web/assets/stylesheets/layout.css +26 -0
- data/web/assets/stylesheets/vendor/bootstrap-responsive.css +567 -0
- data/web/assets/stylesheets/vendor/bootstrap.css +3365 -0
- data/web/views/_paging.slim +15 -0
- data/web/views/_summary.slim +9 -0
- data/web/views/_workers.slim +14 -0
- data/web/views/index.slim +10 -0
- data/web/views/layout.slim +37 -0
- data/web/views/poll.slim +3 -0
- data/web/views/queue.slim +15 -0
- data/web/views/queues.slim +19 -0
- data/web/views/retries.slim +31 -0
- data/web/views/retry.slim +52 -0
- data/web/views/scheduled.slim +27 -0
- metadata +341 -23
- data/lib/creeper/celluloid_ext.rb +0 -42
- data/lib/creeper/creep.rb +0 -25
- data/lib/creeper/err_logger.rb +0 -37
- data/lib/creeper/launcher.rb +0 -44
- data/lib/creeper/out_logger.rb +0 -39
- data/spec/lib/creeper/session_spec.rb +0 -15
- data/spec/lib/creeper/worker_spec.rb +0 -21
data/.gitignore
CHANGED
data/.rvmrc
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
# This is an RVM Project .rvmrc file, used to automatically load the ruby
|
|
4
|
+
# development environment upon cd'ing into the directory
|
|
5
|
+
|
|
6
|
+
# First we specify our desired <ruby>[@<gemset>], the @gemset name is optional,
|
|
7
|
+
# Only full ruby name is supported here, for short names use:
|
|
8
|
+
# echo "rvm use 1.9.3" > .rvmrc
|
|
9
|
+
environment_id="ruby-1.9.3-p194@creeper"
|
|
10
|
+
|
|
11
|
+
# Uncomment the following lines if you want to verify rvm version per project
|
|
12
|
+
# rvmrc_rvm_version="1.15.0 (master)" # 1.10.1 seams as a safe start
|
|
13
|
+
# eval "$(echo ${rvm_version}.${rvmrc_rvm_version} | awk -F. '{print "[[ "$1*65536+$2*256+$3" -ge "$4*65536+$5*256+$6" ]]"}' )" || {
|
|
14
|
+
# echo "This .rvmrc file requires at least RVM ${rvmrc_rvm_version}, aborting loading."
|
|
15
|
+
# return 1
|
|
16
|
+
# }
|
|
17
|
+
|
|
18
|
+
# First we attempt to load the desired environment directly from the environment
|
|
19
|
+
# file. This is very fast and efficient compared to running through the entire
|
|
20
|
+
# CLI and selector. If you want feedback on which environment was used then
|
|
21
|
+
# insert the word 'use' after --create as this triggers verbose mode.
|
|
22
|
+
if [[ -d "${rvm_path:-$HOME/.rvm}/environments"
|
|
23
|
+
&& -s "${rvm_path:-$HOME/.rvm}/environments/$environment_id" ]]
|
|
24
|
+
then
|
|
25
|
+
\. "${rvm_path:-$HOME/.rvm}/environments/$environment_id"
|
|
26
|
+
[[ -s "${rvm_path:-$HOME/.rvm}/hooks/after_use" ]] &&
|
|
27
|
+
\. "${rvm_path:-$HOME/.rvm}/hooks/after_use" || true
|
|
28
|
+
else
|
|
29
|
+
# If the environment file has not yet been created, use the RVM CLI to select.
|
|
30
|
+
rvm --create "$environment_id" || {
|
|
31
|
+
echo "Failed to create RVM environment '${environment_id}'."
|
|
32
|
+
return 1
|
|
33
|
+
}
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
# If you use bundler, this might be useful to you:
|
|
37
|
+
# if [[ -s Gemfile ]] && {
|
|
38
|
+
# ! builtin command -v bundle >/dev/null ||
|
|
39
|
+
# builtin command -v bundle | GREP_OPTIONS= \grep $rvm_path/bin/bundle >/dev/null
|
|
40
|
+
# }
|
|
41
|
+
# then
|
|
42
|
+
# printf "%b" "The rubygem 'bundler' is not installed. Installing it now.\n"
|
|
43
|
+
# gem install bundler
|
|
44
|
+
# fi
|
|
45
|
+
# if [[ -s Gemfile ]] && builtin command -v bundle >/dev/null
|
|
46
|
+
# then
|
|
47
|
+
# bundle install | GREP_OPTIONS= \grep -vE '^Using|Your bundle is complete'
|
|
48
|
+
# fi
|
data/Gemfile
CHANGED
|
@@ -3,4 +3,20 @@ source 'https://rubygems.org'
|
|
|
3
3
|
# Specify your gem's dependencies in creeper.gemspec
|
|
4
4
|
gemspec
|
|
5
5
|
|
|
6
|
-
gem '
|
|
6
|
+
gem 'rails', '3.2.8'
|
|
7
|
+
|
|
8
|
+
gem 'slim'
|
|
9
|
+
gem 'sprockets'
|
|
10
|
+
gem 'sass'
|
|
11
|
+
|
|
12
|
+
group :test do
|
|
13
|
+
## guard ##
|
|
14
|
+
gem 'coolline'
|
|
15
|
+
gem 'guard'
|
|
16
|
+
gem 'guard-rspec'
|
|
17
|
+
gem 'guard-spork'
|
|
18
|
+
|
|
19
|
+
gem 'growl', require: !!(RUBY_PLATFORM =~ /darwin/i) ? 'growl' : false
|
|
20
|
+
gem 'libnotify', require: !!(RUBY_PLATFORM =~ /linux/i) ? 'libnotify' : false
|
|
21
|
+
gem 'terminal-notifier', require: !!(RUBY_PLATFORM =~ /darwin/i) ? 'growl' : false
|
|
22
|
+
end
|
data/Guardfile
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# A sample Guardfile
|
|
2
|
+
# More info at https://github.com/guard/guard#readme
|
|
3
|
+
|
|
4
|
+
guard 'spork', cucumber: false, test_unit: false, rspec: true, bundler: false, wait: 15, rspec_env: { 'RAILS_ENV' => 'test' } do
|
|
5
|
+
watch('Gemfile')
|
|
6
|
+
watch('Gemfile.lock')
|
|
7
|
+
watch('spec/spec_helper.rb') { :rspec }
|
|
8
|
+
watch('test/test_helper.rb') { :test_unit }
|
|
9
|
+
watch(%r{features/support/}) { :cucumber }
|
|
10
|
+
watch(%r{^spec/support/(.+)\.rb$}) { :rspec }
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
guard 'rspec', version: 2, bundler: false, all_after_pass: !ENV['ALL'].nil?, all_on_start: !ENV['ALL'].nil?, cli: '--drb --colour --format nested' do
|
|
14
|
+
watch(%r{^spec/.+_spec\.rb$})
|
|
15
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
|
16
|
+
watch('spec/spec_helper.rb') { "spec" }
|
|
17
|
+
|
|
18
|
+
# Rails example
|
|
19
|
+
watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
|
20
|
+
watch(%r{^app/(.*)(\.erb|\.haml)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
|
|
21
|
+
watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
|
|
22
|
+
watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
|
|
23
|
+
watch('config/routes.rb') { "spec/routing" }
|
|
24
|
+
watch('app/controllers/application_controller.rb') { "spec/controllers" }
|
|
25
|
+
|
|
26
|
+
# Capybara request specs
|
|
27
|
+
watch(%r{^app/views/(.+)/.*\.(erb|haml)$}) { |m| "spec/requests/#{m[1]}_spec.rb" }
|
|
28
|
+
|
|
29
|
+
# Turnip features and steps
|
|
30
|
+
watch(%r{^spec/acceptance/(.+)\.feature$})
|
|
31
|
+
watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
|
|
32
|
+
end
|
data/Rakefile
CHANGED
data/bin/creeper
CHANGED
|
@@ -1,62 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
opts.separator "Ruby options:"
|
|
15
|
-
|
|
16
|
-
opts.on("-d", "--debug", "set debugging flags (set $DEBUG to true)") do
|
|
17
|
-
$DEBUG = true
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
opts.separator "#{cmd} options:"
|
|
21
|
-
|
|
22
|
-
opts.on("-D", "--daemonize", "run daemonized in the background") do |d|
|
|
23
|
-
options[:daemonize] = !!d
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
opts.on("-j", "--job-file FILE", "Creeper-specific job file") do |f|
|
|
27
|
-
options[:job_file] = f
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
opts.on("-r", "--runner-count NUMBER", "Threads to run (default: #{options[:runner_count]})") do |r|
|
|
31
|
-
options[:runner_count] = (r.to_i rescue 1)
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
opts.separator "Common options:"
|
|
35
|
-
|
|
36
|
-
opts.on_tail("-h", "--help", "Show this message") do
|
|
37
|
-
puts opts.to_s.gsub(/^.*DEPRECATED.*$/s, '')
|
|
38
|
-
exit
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
opts.on_tail("-v", "--version", "Show version") do
|
|
42
|
-
puts "#{cmd} v#{Creeper::VERSION}"
|
|
43
|
-
exit
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
opts.parse! ARGV
|
|
47
|
-
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
unless options[:job_file]
|
|
51
|
-
$stderr.puts "ERROR: job file required", ''
|
|
52
|
-
puts op.to_s.gsub(/^.*DEPRECATED.*$/s, '')
|
|
3
|
+
require_relative '../lib/creeper/cli'
|
|
4
|
+
|
|
5
|
+
begin
|
|
6
|
+
cli = Creeper::CLI.instance
|
|
7
|
+
cli.parse
|
|
8
|
+
cli.run
|
|
9
|
+
rescue => e
|
|
10
|
+
raise e if $DEBUG
|
|
11
|
+
STDERR.puts e.message
|
|
12
|
+
STDERR.puts e.backtrace.join("\n")
|
|
53
13
|
exit 1
|
|
54
14
|
end
|
|
55
|
-
|
|
56
|
-
if $DEBUG
|
|
57
|
-
require 'pp'
|
|
58
|
-
pp(options)
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
Creeper::Launcher.launch!(options) if options[:daemonize]
|
|
62
|
-
Creeper.new(options).start.join
|
data/bin/creeperctl
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require 'fileutils'
|
|
4
|
+
|
|
5
|
+
class Creeperctl
|
|
6
|
+
|
|
7
|
+
attr_reader :stage, :pidfile, :timeout
|
|
8
|
+
|
|
9
|
+
def initialize(stage, pidfile, timeout)
|
|
10
|
+
@stage = stage
|
|
11
|
+
@pidfile = pidfile
|
|
12
|
+
@timeout = timeout
|
|
13
|
+
|
|
14
|
+
done 'No pidfile given' if !pidfile
|
|
15
|
+
done "Pidfile #{pidfile} does not exist" if !File.exist?(pidfile)
|
|
16
|
+
done 'Invalid pidfile content' if pid == 0
|
|
17
|
+
|
|
18
|
+
fetch_process
|
|
19
|
+
|
|
20
|
+
begin
|
|
21
|
+
send(stage)
|
|
22
|
+
rescue NoMethodError
|
|
23
|
+
done 'Invalid control command'
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def fetch_process
|
|
28
|
+
Process.getpgid(pid)
|
|
29
|
+
rescue Errno::ESRCH
|
|
30
|
+
done "Process doesn't exist"
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def done(msg)
|
|
34
|
+
puts msg
|
|
35
|
+
exit(0)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def pid
|
|
39
|
+
File.read(pidfile).to_i
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def quiet
|
|
43
|
+
`kill -USR1 #{pid}`
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def stop
|
|
47
|
+
`kill -TERM #{pid}`
|
|
48
|
+
timeout.times do
|
|
49
|
+
begin
|
|
50
|
+
Process.getpgid(pid)
|
|
51
|
+
rescue Errno::ESRCH
|
|
52
|
+
FileUtils.rm_f pidfile
|
|
53
|
+
done 'Creeper shut down gracefully.'
|
|
54
|
+
end
|
|
55
|
+
sleep 1
|
|
56
|
+
end
|
|
57
|
+
`kill -9 #{pid}`
|
|
58
|
+
FileUtils.rm_f pidfile
|
|
59
|
+
done 'Creeper shut down forcefully.'
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def shutdown
|
|
63
|
+
quiet
|
|
64
|
+
stop
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
stage = ARGV[0]
|
|
70
|
+
pidfile = ARGV[1]
|
|
71
|
+
timeout = ARGV[2].to_i
|
|
72
|
+
timeout = 10 if timeout == 0
|
|
73
|
+
|
|
74
|
+
Creeperctl.new(stage, pidfile, timeout)
|
data/config.ru
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
require 'creeper'
|
|
2
|
+
|
|
3
|
+
Creeper.configure_client do |config|
|
|
4
|
+
config.redis = { :size => 1 }
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
#Creeper.redis {|conn| conn.flushdb }
|
|
8
|
+
#10.times do |idx|
|
|
9
|
+
#Creeper::Client.push('class' => 'HardWorker', 'args' => ['foo', 0.1, idx])
|
|
10
|
+
#end
|
|
11
|
+
|
|
12
|
+
#Creeper.redis { |conn| conn.zadd('retry', Time.now.utc.to_f + 3000, MultiJson.encode({
|
|
13
|
+
#'class' => 'HardWorker', 'args' => ['foo', 0.1, Time.now.to_f],
|
|
14
|
+
#'queue' => 'default', 'error_message' => 'No such method', 'error_class' => 'NoMethodError',
|
|
15
|
+
#'failed_at' => Time.now.utc, 'retry_count' => 0 })) }
|
|
16
|
+
|
|
17
|
+
require 'creeper/web'
|
|
18
|
+
run Creeper::Web
|
data/creeper.gemspec
CHANGED
|
@@ -1,25 +1,35 @@
|
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
|
2
|
-
|
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
|
+
require 'creeper/version'
|
|
3
5
|
|
|
4
6
|
Gem::Specification.new do |gem|
|
|
7
|
+
gem.name = "creeper"
|
|
8
|
+
gem.version = Creeper::VERSION
|
|
5
9
|
gem.authors = ["Lyon Hill", "Andrew Bennett"]
|
|
6
10
|
gem.email = ["lyondhill@gmail.com", "potatosaladx@gmail.com"]
|
|
7
11
|
gem.description = %q{Creeper is an evented version of Stalker}
|
|
8
12
|
gem.summary = %q{A better solution for io bound jobs, same as stalker in functionality but more evented}
|
|
9
13
|
gem.homepage = "https://github.com/potatosalad/creeper"
|
|
10
14
|
|
|
11
|
-
gem.files = `git ls-files`.split(
|
|
12
|
-
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
|
15
|
+
gem.files = `git ls-files`.split($/)
|
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) } + ['creeperctl']
|
|
13
17
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
|
14
|
-
gem.name = "creeper"
|
|
15
18
|
gem.require_paths = ["lib"]
|
|
16
|
-
|
|
19
|
+
|
|
20
|
+
gem.add_dependency 'redis', '~> 3'
|
|
21
|
+
gem.add_dependency 'redis-namespace'
|
|
22
|
+
gem.add_dependency 'beanstalk-client'
|
|
23
|
+
gem.add_dependency 'connection_pool', '~> 0.9.2'
|
|
24
|
+
gem.add_dependency 'celluloid', '~> 0.11.1'
|
|
25
|
+
gem.add_dependency 'kgio'
|
|
26
|
+
gem.add_dependency 'multi_json', '~> 1'
|
|
17
27
|
|
|
18
28
|
gem.add_development_dependency 'pry'
|
|
19
29
|
gem.add_development_dependency 'rake'
|
|
20
30
|
gem.add_development_dependency 'rspec'
|
|
21
|
-
|
|
22
|
-
gem.
|
|
23
|
-
gem.
|
|
24
|
-
gem.
|
|
31
|
+
gem.add_development_dependency 'sinatra'
|
|
32
|
+
gem.add_development_dependency 'slim'
|
|
33
|
+
gem.add_development_dependency 'actionmailer', '~> 3'
|
|
34
|
+
gem.add_development_dependency 'activerecord', '~> 3'
|
|
25
35
|
end
|
data/lib/creeper.rb
CHANGED
|
@@ -1,443 +1,138 @@
|
|
|
1
|
-
require 'beanstalk-client'
|
|
2
|
-
require 'json'
|
|
3
|
-
require 'logger'
|
|
4
|
-
require 'thread'
|
|
5
|
-
require 'timeout'
|
|
6
|
-
require 'uri'
|
|
7
|
-
|
|
8
1
|
require 'creeper/version'
|
|
2
|
+
require 'creeper/logging'
|
|
3
|
+
require 'creeper/client'
|
|
4
|
+
require 'creeper/worker'
|
|
5
|
+
require 'creeper/beanstalk_connection'
|
|
6
|
+
require 'creeper/redis_connection'
|
|
7
|
+
require 'creeper/util'
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class BadURL < RuntimeError; end
|
|
13
|
-
|
|
14
|
-
HANDLERS = {
|
|
15
|
-
named: {},
|
|
16
|
-
before_each: [],
|
|
17
|
-
before_named: {},
|
|
18
|
-
after_each: [],
|
|
19
|
-
after_named: {},
|
|
20
|
-
error_each: [],
|
|
21
|
-
error_named: {},
|
|
22
|
-
finalizers: []
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
WORKERS = {}
|
|
26
|
-
|
|
27
|
-
## default configuration ##
|
|
28
|
-
|
|
29
|
-
@patience_soft = 60
|
|
30
|
-
@patience_hard = 30
|
|
31
|
-
@pool_size = 2
|
|
32
|
-
@retry_count = 3
|
|
33
|
-
@reserve_timeout = 1
|
|
34
|
-
|
|
35
|
-
@lock = Mutex.new
|
|
36
|
-
|
|
37
|
-
##
|
|
38
|
-
|
|
39
|
-
class << self
|
|
40
|
-
|
|
41
|
-
## configuration ##
|
|
42
|
-
|
|
43
|
-
attr_reader :lock
|
|
44
|
-
attr_accessor :patience_soft, :patience_hard, :pool_size, :reserve_timeout, :retry_count
|
|
45
|
-
|
|
46
|
-
def beanstalk_url
|
|
47
|
-
lock.synchronize do
|
|
48
|
-
@beanstalk_url ||= ENV['BEANSTALK_URL'] || 'beanstalk://127.0.0.1/'
|
|
49
|
-
end
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
def beanstalk_url=(beanstalk_url)
|
|
53
|
-
lock.synchronize do
|
|
54
|
-
@beanstalk_url = beanstalk_url
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
def err_logger
|
|
59
|
-
lock.synchronize do
|
|
60
|
-
@err_logger ||= ::Logger.new($stderr)
|
|
61
|
-
end
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
def err_logger=(err_logger)
|
|
65
|
-
lock.synchronize do
|
|
66
|
-
@err_logger = err_logger
|
|
67
|
-
end
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
def out_logger
|
|
71
|
-
lock.synchronize do
|
|
72
|
-
@out_logger ||= ::Logger.new($stdout)
|
|
73
|
-
end
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
def out_logger=(out_logger)
|
|
77
|
-
lock.synchronize do
|
|
78
|
-
@out_logger = out_logger
|
|
79
|
-
end
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
def worker_pool
|
|
83
|
-
lock.synchronize do
|
|
84
|
-
@worker_pool
|
|
85
|
-
end
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
def worker_pool=(worker_pool)
|
|
89
|
-
lock.synchronize do
|
|
90
|
-
@worker_pool = worker_pool
|
|
91
|
-
end
|
|
92
|
-
end
|
|
9
|
+
require 'creeper/legacy'
|
|
93
10
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
end
|
|
98
|
-
end
|
|
11
|
+
require 'creeper/extensions/action_mailer'
|
|
12
|
+
require 'creeper/extensions/active_record'
|
|
13
|
+
require 'creeper/rails' if defined?(::Rails::Engine)
|
|
99
14
|
|
|
100
|
-
|
|
101
|
-
lock.synchronize do
|
|
102
|
-
@shutdown = shutdown
|
|
103
|
-
end
|
|
104
|
-
end
|
|
15
|
+
require 'multi_json'
|
|
105
16
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
## connection ##
|
|
109
|
-
|
|
110
|
-
def beanstalk
|
|
111
|
-
Thread.current[:beanstalk_pool_connection] ||= connect
|
|
112
|
-
end
|
|
113
|
-
|
|
114
|
-
def beanstalk_addresses
|
|
115
|
-
uris = beanstalk_url.split(/[\s,]+/)
|
|
116
|
-
uris.map do |uri|
|
|
117
|
-
beanstalk_host_and_port(uri)
|
|
118
|
-
end
|
|
119
|
-
end
|
|
120
|
-
|
|
121
|
-
def connect(addresses = nil)
|
|
122
|
-
Beanstalk::Pool.new(addresses || beanstalk_addresses)
|
|
123
|
-
end
|
|
124
|
-
|
|
125
|
-
def disconnect
|
|
126
|
-
Thread.current[:beanstalk_pool_connection].close rescue nil
|
|
127
|
-
Thread.current[:beanstalk_pool_connection] = nil
|
|
128
|
-
end
|
|
129
|
-
|
|
130
|
-
##
|
|
131
|
-
|
|
132
|
-
## daemon ##
|
|
133
|
-
|
|
134
|
-
def work(jobs = nil, size = nil)
|
|
135
|
-
require 'creeper/worker'
|
|
136
|
-
|
|
137
|
-
Creeper.pool_size = size || Creeper.pool_size
|
|
138
|
-
|
|
139
|
-
Creeper::Worker.work(jobs, Creeper.pool_size)
|
|
140
|
-
end
|
|
141
|
-
|
|
142
|
-
##
|
|
143
|
-
|
|
144
|
-
## handlers ##
|
|
145
|
-
|
|
146
|
-
def all_jobs
|
|
147
|
-
lock.synchronize do
|
|
148
|
-
HANDLERS[:named].keys
|
|
149
|
-
end
|
|
150
|
-
end
|
|
151
|
-
|
|
152
|
-
def job(name, &block)
|
|
153
|
-
lock.synchronize do
|
|
154
|
-
HANDLERS[:named][name] = block
|
|
155
|
-
HANDLERS[:before_named][name] ||= []
|
|
156
|
-
HANDLERS[:after_named][name] ||= []
|
|
157
|
-
HANDLERS[:error_named][name] ||= []
|
|
158
|
-
HANDLERS[:named][name]
|
|
159
|
-
end
|
|
160
|
-
end
|
|
161
|
-
|
|
162
|
-
def drop(name)
|
|
163
|
-
lock.synchronize do
|
|
164
|
-
HANDLERS[:named].delete(name)
|
|
165
|
-
HANDLERS[:before_named].delete(name)
|
|
166
|
-
HANDLERS[:after_named].delete(name)
|
|
167
|
-
HANDLERS[:error_named].delete(name)
|
|
168
|
-
true
|
|
169
|
-
end
|
|
170
|
-
end
|
|
171
|
-
|
|
172
|
-
def handler_for(name)
|
|
173
|
-
lock.synchronize do
|
|
174
|
-
HANDLERS[:named][name]
|
|
175
|
-
end
|
|
176
|
-
end
|
|
177
|
-
|
|
178
|
-
def before(name = nil, &block)
|
|
179
|
-
if name and name != :each
|
|
180
|
-
lock.synchronize do
|
|
181
|
-
HANDLERS[:before_named][name] << block
|
|
182
|
-
end
|
|
183
|
-
else
|
|
184
|
-
lock.synchronize do
|
|
185
|
-
HANDLERS[:before_each] << block
|
|
186
|
-
end
|
|
187
|
-
end
|
|
188
|
-
end
|
|
189
|
-
|
|
190
|
-
def before_handlers_for(name)
|
|
191
|
-
lock.synchronize do
|
|
192
|
-
HANDLERS[:before_each] + HANDLERS[:before_named][name]
|
|
193
|
-
end
|
|
194
|
-
end
|
|
195
|
-
|
|
196
|
-
def after(name = nil, &block)
|
|
197
|
-
if name and name != :each
|
|
198
|
-
lock.synchronize do
|
|
199
|
-
HANDLERS[:after_named][name] << block
|
|
200
|
-
end
|
|
201
|
-
else
|
|
202
|
-
lock.synchronize do
|
|
203
|
-
HANDLERS[:after_each] << block
|
|
204
|
-
end
|
|
205
|
-
end
|
|
206
|
-
end
|
|
207
|
-
|
|
208
|
-
def after_handlers_for(name)
|
|
209
|
-
lock.synchronize do
|
|
210
|
-
HANDLERS[:after_each] + HANDLERS[:after_named][name]
|
|
211
|
-
end
|
|
212
|
-
end
|
|
213
|
-
|
|
214
|
-
def error(name = nil, &block)
|
|
215
|
-
if name and name != :each
|
|
216
|
-
lock.synchronize do
|
|
217
|
-
HANDLERS[:error_named][name] << block
|
|
218
|
-
end
|
|
219
|
-
else
|
|
220
|
-
lock.synchronize do
|
|
221
|
-
HANDLERS[:error_each] << block
|
|
222
|
-
end
|
|
223
|
-
end
|
|
224
|
-
end
|
|
225
|
-
|
|
226
|
-
def error_handlers_for(name)
|
|
227
|
-
lock.synchronize do
|
|
228
|
-
HANDLERS[:error_each] + HANDLERS[:error_named][name]
|
|
229
|
-
end
|
|
230
|
-
end
|
|
231
|
-
|
|
232
|
-
def finalizer(&block)
|
|
233
|
-
lock.synchronize do
|
|
234
|
-
HANDLERS[:finalizers] << block
|
|
235
|
-
end
|
|
236
|
-
end
|
|
237
|
-
|
|
238
|
-
def finalizers
|
|
239
|
-
lock.synchronize do
|
|
240
|
-
HANDLERS[:finalizers]
|
|
241
|
-
end
|
|
242
|
-
end
|
|
243
|
-
|
|
244
|
-
##
|
|
245
|
-
|
|
246
|
-
## queue ##
|
|
247
|
-
|
|
248
|
-
def enqueue(job, data = {}, options = {})
|
|
249
|
-
# OutLogger.debug "#{Thread.current[:actor].inspect} Enqueueing #{job.inspect}, #{data.inspect}"#\n#{Celluloid::Actor.all.pretty_inspect}"
|
|
250
|
-
OutLogger.debug "[#{Thread.current[:actor] ? Thread.current[:actor].subject.number : nil}] Enqueueing #{job.inspect}, #{data.inspect}" if $DEBUG
|
|
251
|
-
enqueue!(job, data, options)
|
|
252
|
-
rescue Beanstalk::NotConnected => e
|
|
253
|
-
disconnected(self, :enqueue, job, data, options)
|
|
254
|
-
end
|
|
255
|
-
|
|
256
|
-
def enqueue!(job, data = {}, options = {})
|
|
257
|
-
priority = options[:priority] || options[:pri] || 65536
|
|
258
|
-
delay = [ 0, options[:delay].to_i ].max
|
|
259
|
-
time_to_run = options[:time_to_run] || options[:ttr] || 120
|
|
260
|
-
|
|
261
|
-
beanstalk.use job
|
|
262
|
-
beanstalk.put JSON.dump([ job, data ]), priority, delay, time_to_run
|
|
263
|
-
end
|
|
264
|
-
|
|
265
|
-
##
|
|
266
|
-
|
|
267
|
-
## workers ##
|
|
268
|
-
|
|
269
|
-
def error_work(worker, data, name, job)
|
|
270
|
-
(worker.stopped_at = Time.now).tap do |stopped_at|
|
|
271
|
-
error_message = "#{worker.prefix} Error after #{worker.time_in_milliseconds}ms #{worker.dump(job, name, data)}"
|
|
272
|
-
OutLogger.error error_message
|
|
273
|
-
end
|
|
274
|
-
end
|
|
17
|
+
module Creeper
|
|
275
18
|
|
|
276
|
-
|
|
277
|
-
lock.synchronize do
|
|
278
|
-
number = ((0..(WORKERS.keys.max || 0)+1).to_a - WORKERS.keys).first
|
|
279
|
-
WORKERS[number] = worker.tap do
|
|
280
|
-
worker.number = number
|
|
281
|
-
end
|
|
282
|
-
end
|
|
283
|
-
end
|
|
19
|
+
extend Creeper::Legacy::ClassMethods
|
|
284
20
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
end
|
|
294
|
-
end
|
|
295
|
-
end
|
|
21
|
+
DEFAULTS = {
|
|
22
|
+
:queues => [],
|
|
23
|
+
:concurrency => 25,
|
|
24
|
+
:require => '.',
|
|
25
|
+
:environment => nil,
|
|
26
|
+
:timeout => 8,
|
|
27
|
+
:enable_rails_extensions => true,
|
|
28
|
+
}
|
|
296
29
|
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
end
|
|
301
|
-
end
|
|
30
|
+
def self.options
|
|
31
|
+
@options ||= DEFAULTS.dup
|
|
32
|
+
end
|
|
302
33
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
end
|
|
307
|
-
end
|
|
34
|
+
def self.options=(opts)
|
|
35
|
+
@options = opts
|
|
36
|
+
end
|
|
308
37
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
38
|
+
##
|
|
39
|
+
# Configuration for Creeper server, use like:
|
|
40
|
+
#
|
|
41
|
+
# Creeper.configure_server do |config|
|
|
42
|
+
# config.redis = { :namespace => 'myapp', :size => 25, :url => 'redis://myhost:8877/mydb' }
|
|
43
|
+
# config.server_middleware do |chain|
|
|
44
|
+
# chain.add MyServerHook
|
|
45
|
+
# end
|
|
46
|
+
# end
|
|
47
|
+
def self.configure_server
|
|
48
|
+
yield self if server?
|
|
49
|
+
end
|
|
316
50
|
|
|
317
|
-
|
|
51
|
+
##
|
|
52
|
+
# Configuration for Creeper client, use like:
|
|
53
|
+
#
|
|
54
|
+
# Creeper.configure_client do |config|
|
|
55
|
+
# config.redis = { :namespace => 'myapp', :size => 1, :url => 'redis://myhost:8877/mydb' }
|
|
56
|
+
# end
|
|
57
|
+
def self.configure_client
|
|
58
|
+
yield self unless server?
|
|
59
|
+
end
|
|
318
60
|
|
|
319
|
-
|
|
61
|
+
def self.server?
|
|
62
|
+
defined?(Creeper::CLI)
|
|
63
|
+
end
|
|
320
64
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
65
|
+
def self.beanstalk(&block)
|
|
66
|
+
if block_given?
|
|
67
|
+
yield beanstalk
|
|
68
|
+
else
|
|
69
|
+
@beanstalk ||= Creeper::BeanstalkConnection.create
|
|
325
70
|
end
|
|
71
|
+
end
|
|
326
72
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
if Thread.current[:beanstalk_connection_retries] >= retry_count
|
|
331
|
-
OutLogger.error "Unable to connect to beanstalk after #{Thread.current[:beanstalk_connection_retries]} attempts"
|
|
332
|
-
Thread.current[:beanstalk_connection_retries] = 0
|
|
333
|
-
return false
|
|
334
|
-
end
|
|
335
|
-
|
|
336
|
-
disconnect
|
|
337
|
-
|
|
338
|
-
Thread.current[:beanstalk_connection_retries] += 1
|
|
339
|
-
|
|
340
|
-
sleep Thread.current[:beanstalk_connection_retries] * 2
|
|
341
|
-
|
|
342
|
-
target.send(method, *args, &block)
|
|
73
|
+
def self.beanstalk=(hash)
|
|
74
|
+
if @beanstalk
|
|
75
|
+
@beanstalk.close rescue nil
|
|
343
76
|
end
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
# Attempt to shut down the supervision tree, if available
|
|
351
|
-
Celluloid::Supervisor.root.terminate if Celluloid::Supervisor.root
|
|
352
|
-
|
|
353
|
-
# Actors cannot self-terminate, you must do it for them
|
|
354
|
-
starts = working_actors.map do |actor|
|
|
355
|
-
begin
|
|
356
|
-
if actor.alive?
|
|
357
|
-
actor.stop! # fire and forget for those already working
|
|
358
|
-
actor.future(:start, true) # ensures that the mailbox is cleared out
|
|
359
|
-
end
|
|
360
|
-
rescue Celluloid::DeadActorError, Celluloid::MailboxError
|
|
361
|
-
end
|
|
362
|
-
end.compact
|
|
363
|
-
|
|
364
|
-
starts.each do |start|
|
|
365
|
-
begin
|
|
366
|
-
start.value
|
|
367
|
-
rescue Celluloid::DeadActorError, Celluloid::MailboxError
|
|
368
|
-
end
|
|
369
|
-
end
|
|
370
|
-
|
|
371
|
-
OutLogger.info "Graceful stop completed cleanly"
|
|
372
|
-
end
|
|
77
|
+
if hash.is_a?(Hash)
|
|
78
|
+
@beanstalk = BeanstalkConnection.create(hash)
|
|
79
|
+
elsif hash.is_a?(Beanstalk::Pool)
|
|
80
|
+
@beanstalk = hash
|
|
81
|
+
else
|
|
82
|
+
raise ArgumentError, "beanstalk= requires a Hash or Beanstalk::Pool"
|
|
373
83
|
end
|
|
84
|
+
end
|
|
374
85
|
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
# Attempt to shut down the supervision tree, if available
|
|
381
|
-
Celluloid::Supervisor.root.terminate if Celluloid::Supervisor.root
|
|
382
|
-
|
|
383
|
-
pool_managers.each do |pool_manager|
|
|
384
|
-
begin
|
|
385
|
-
pool_manager.terminate
|
|
386
|
-
rescue Celluloid::DeadActorError, Celluloid::MailboxError
|
|
387
|
-
end
|
|
388
|
-
end
|
|
389
|
-
|
|
390
|
-
# Actors cannot self-terminate, you must do it for them
|
|
391
|
-
working_actors.each do |actor|
|
|
392
|
-
begin
|
|
393
|
-
actor.terminate
|
|
394
|
-
rescue Celluloid::DeadActorError, Celluloid::MailboxError
|
|
395
|
-
end
|
|
396
|
-
end
|
|
86
|
+
def self.redis(&block)
|
|
87
|
+
@redis ||= Creeper::RedisConnection.create
|
|
88
|
+
raise ArgumentError, "requires a block" if !block
|
|
89
|
+
@redis.with(&block)
|
|
90
|
+
end
|
|
397
91
|
|
|
398
|
-
|
|
399
|
-
|
|
92
|
+
def self.redis=(hash)
|
|
93
|
+
if hash.is_a?(Hash)
|
|
94
|
+
@redis = RedisConnection.create(hash)
|
|
95
|
+
elsif hash.is_a?(ConnectionPool)
|
|
96
|
+
@redis = hash
|
|
97
|
+
else
|
|
98
|
+
raise ArgumentError, "redis= requires a Hash or ConnectionPool"
|
|
400
99
|
end
|
|
100
|
+
end
|
|
401
101
|
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
102
|
+
def self.client_middleware
|
|
103
|
+
@client_chain ||= Client.default_middleware
|
|
104
|
+
yield @client_chain if block_given?
|
|
105
|
+
@client_chain
|
|
106
|
+
end
|
|
405
107
|
|
|
406
|
-
|
|
407
|
-
|
|
108
|
+
def self.server_middleware
|
|
109
|
+
@server_chain ||= Processor.default_middleware
|
|
110
|
+
yield @server_chain if block_given?
|
|
111
|
+
@server_chain
|
|
112
|
+
end
|
|
408
113
|
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
actor.kill
|
|
413
|
-
actor.join
|
|
414
|
-
rescue Celluloid::DeadActorError, Celluloid::MailboxError
|
|
415
|
-
end
|
|
416
|
-
end
|
|
114
|
+
def self.server?
|
|
115
|
+
defined?(Creeper::CLI)
|
|
116
|
+
end
|
|
417
117
|
|
|
418
|
-
|
|
419
|
-
|
|
118
|
+
def self.load_json(string)
|
|
119
|
+
MultiJson.decode(string)
|
|
120
|
+
end
|
|
420
121
|
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
actor.is_a?(Celluloid::PoolManager) rescue false
|
|
425
|
-
end
|
|
426
|
-
end
|
|
427
|
-
end
|
|
122
|
+
def self.dump_json(object)
|
|
123
|
+
MultiJson.encode(object)
|
|
124
|
+
end
|
|
428
125
|
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
actor.is_a?(Celluloid::PoolManager) rescue false
|
|
433
|
-
end
|
|
434
|
-
end
|
|
435
|
-
end
|
|
126
|
+
def self.logger
|
|
127
|
+
Creeper::Logging.logger
|
|
128
|
+
end
|
|
436
129
|
|
|
130
|
+
def self.logger=(log)
|
|
131
|
+
Creeper::Logging.logger = log
|
|
437
132
|
end
|
|
438
133
|
|
|
439
|
-
|
|
134
|
+
def self.poll_interval=(interval)
|
|
135
|
+
self.options[:poll_interval] = interval
|
|
136
|
+
end
|
|
440
137
|
|
|
441
|
-
|
|
442
|
-
require 'creeper/err_logger'
|
|
443
|
-
require 'creeper/out_logger'
|
|
138
|
+
end
|