patriot-workflow-scheduler 0.7.2 → 0.8.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.
- checksums.yaml +8 -8
- data/lib/patriot.rb +1 -0
- data/lib/patriot/command.rb +11 -11
- data/lib/patriot/command/base.rb +3 -3
- data/lib/patriot/command/composite.rb +20 -6
- data/lib/patriot/command/post_processor.rb +2 -2
- data/lib/patriot/command/post_processor/base.rb +3 -2
- data/lib/patriot/command/post_processor/mail_notification.rb +3 -3
- data/lib/patriot/command/post_processor/retrial.rb +3 -3
- data/lib/patriot/command/sh_command.rb +14 -0
- data/lib/patriot/controller/worker_admin_controller.rb +13 -8
- data/lib/patriot/job_store/base.rb +16 -7
- data/lib/patriot/job_store/in_memory_store.rb +121 -29
- data/lib/patriot/job_store/job.rb +7 -7
- data/lib/patriot/job_store/job_ticket.rb +1 -0
- data/lib/patriot/job_store/rdb_job_store.rb +161 -54
- data/lib/patriot/tool/patriot_commands/execute.rb +1 -1
- data/lib/patriot/tool/patriot_commands/job.rb +6 -4
- data/lib/patriot/tool/patriot_commands/register.rb +7 -5
- data/lib/patriot/util/config.rb +14 -3
- data/lib/patriot/util/config/inifile_config.rb +1 -1
- data/lib/patriot/version.rb +3 -0
- data/lib/patriot/worker/base.rb +6 -3
- data/lib/patriot/worker/info_server.rb +34 -24
- data/lib/patriot/worker/servlet.rb +4 -8
- data/lib/patriot/worker/servlet/api_servlet_base.rb +40 -0
- data/lib/patriot/worker/servlet/index_servlet.rb +32 -0
- data/lib/patriot/worker/servlet/job_api_servlet.rb +156 -0
- data/lib/patriot/worker/servlet/worker_api_servlet.rb +67 -0
- data/skel/batch/sample/daily/test.pbc +1 -1
- data/skel/public/css/bootstrap.min.css +7412 -0
- data/skel/public/css/original.css +179 -54
- data/skel/public/js/patriot-workflow-scheduler-0.8.0.js +82252 -0
- data/skel/public/js/patriot-workflow-scheduler-0.8.0.min.js +26 -0
- data/skel/public/js/patriot-workflow-scheduler-0.8.0.min.js.map +1 -0
- data/skel/public/templates/_jobs.erb +4 -5
- data/skel/public/templates/job.erb +2 -4
- data/skel/public/templates/layout.erb +10 -10
- data/skel/public/views/index.erb +13 -0
- metadata +40 -4
- data/lib/patriot/worker/servlet/job_servlet.rb +0 -128
- data/lib/patriot/worker/servlet/worker_status_servlet.rb +0 -52
data/lib/patriot/util/config.rb
CHANGED
@@ -14,20 +14,31 @@ module Patriot
|
|
14
14
|
# default plugins directory
|
15
15
|
DEFAULT_PLUGIN_DIR = "plugins"
|
16
16
|
# plugin directory
|
17
|
-
PLUGIN_LIB_DIR = 'lib'
|
17
|
+
PLUGIN_LIB_DIR = 'lib'
|
18
18
|
# plugin initiation script
|
19
19
|
PLUGIN_INIT_SCRIPT = 'init.rb'
|
20
20
|
# admin user mail address
|
21
21
|
ADMIN_USER_KEY = 'admin_user'
|
22
22
|
|
23
|
+
# a comma separated list of hosts where workers are running
|
24
|
+
WORKER_HOST_KEY = 'worker_hosts'
|
25
|
+
# port number used by info server
|
26
|
+
INFO_SERVER_PORT_KEY = 'info_server_port'
|
27
|
+
|
28
|
+
# configuratio key for admin user name
|
29
|
+
USERNAME_KEY = 'info_server.admin.username'
|
30
|
+
# configuratio key for admin password
|
31
|
+
PASSWORD_KEY = 'info_server.admin.password'
|
32
|
+
|
33
|
+
|
23
34
|
# load configuration file
|
24
35
|
# @param option [Hash]
|
25
36
|
# @option option :path [String] path to configuration file
|
26
37
|
# @option option :type [String] load type (differe by tool)
|
27
38
|
# @option option :ignore_plugin [Boolean] set true not to load plugins
|
28
39
|
def load_config(option = {})
|
29
|
-
option = {:path => DEFAULT_CONFIG,
|
30
|
-
:type => nil,
|
40
|
+
option = {:path => DEFAULT_CONFIG,
|
41
|
+
:type => nil,
|
31
42
|
:ignore_plugin => false }.merge(option)
|
32
43
|
conf = nil
|
33
44
|
case File.extname(option[:path])
|
@@ -5,7 +5,7 @@ module Patriot
|
|
5
5
|
# a configuration implementation definied by the ini-file format
|
6
6
|
class IniFileConfig < Patriot::Util::Config::Base
|
7
7
|
|
8
|
-
#
|
8
|
+
# common section name
|
9
9
|
COMMON_SECTION = 'common'
|
10
10
|
|
11
11
|
# @param path [String] path to a configuration file
|
data/lib/patriot/worker/base.rb
CHANGED
@@ -28,12 +28,13 @@ module Patriot
|
|
28
28
|
# @abstract
|
29
29
|
# base class for worker implementations
|
30
30
|
class Base
|
31
|
-
|
31
|
+
|
32
32
|
include Patriot::Util::Logger
|
33
33
|
include Patriot::Util::Retry
|
34
34
|
include Patriot::JobStore::Factory
|
35
|
-
|
35
|
+
|
36
36
|
attr_accessor :host, :status, :cycle, :job_store, :config
|
37
|
+
attr_reader :started_at
|
37
38
|
|
38
39
|
# @param config [Patriot::Util::Config::Base]
|
39
40
|
def initialize(config)
|
@@ -73,6 +74,7 @@ module Patriot
|
|
73
74
|
job_ticket.exit_code = Patriot::Command::ExitCode::SUCCEEDED
|
74
75
|
rescue Exception => e
|
75
76
|
@logger.warn " job : #{job_ticket.job_id} failed"
|
77
|
+
@logger.warn e
|
76
78
|
job_ticket.description = e.to_s
|
77
79
|
else
|
78
80
|
job_ticket.description = command.description
|
@@ -122,6 +124,7 @@ module Patriot
|
|
122
124
|
File.open(pid_file, 'w') {|f| f.write($$)} # save pid for shutdown
|
123
125
|
set_traps
|
124
126
|
@info_server.start_server
|
127
|
+
@started_at = Time.now
|
125
128
|
@logger.info "initiating worker #{@node}@#{@host}"
|
126
129
|
init_worker
|
127
130
|
@status = Patriot::Worker::Status::ACTIVE
|
@@ -136,7 +139,7 @@ module Patriot
|
|
136
139
|
|
137
140
|
# should be overrided in sub class
|
138
141
|
# This method is for implementation-specific configuration
|
139
|
-
def init_worker
|
142
|
+
def init_worker
|
140
143
|
raise NotImplementedError
|
141
144
|
end
|
142
145
|
|
@@ -1,3 +1,6 @@
|
|
1
|
+
require 'thin'
|
2
|
+
require 'rack/rewrite'
|
3
|
+
|
1
4
|
module Patriot
|
2
5
|
module Worker
|
3
6
|
# info server (web management console and for monitoring)
|
@@ -8,15 +11,11 @@ module Patriot
|
|
8
11
|
# default port number
|
9
12
|
DEFAULT_PORT = '36104'
|
10
13
|
|
11
|
-
# urls used by this server
|
12
|
-
URLS_KEY = 'info_server.urls'
|
13
|
-
# mapping from the url to a servlet for the url
|
14
|
-
URL_MAP_KEY_PREFIX = 'info_server.urlmap'
|
15
|
-
|
16
14
|
# configuration key for rack handler used to start this server
|
17
15
|
RACK_HANDLER_KEY = 'info_server.rack.handler'
|
18
16
|
# default rack handler
|
19
|
-
DEFAULT_RACK_HANDLER = 'Rack::Handler::WEBrick'
|
17
|
+
# DEFAULT_RACK_HANDLER = 'Rack::Handler::WEBrick'
|
18
|
+
DEFAULT_RACK_HANDLER = 'Rack::Handler::Thin'
|
20
19
|
|
21
20
|
include Patriot::Util::Config
|
22
21
|
include Patriot::Util::Logger
|
@@ -39,35 +38,41 @@ module Patriot
|
|
39
38
|
@logger.info("port is not set. starting info server is skipped")
|
40
39
|
return
|
41
40
|
end
|
42
|
-
@server_thread = Thread.new do
|
41
|
+
@server_thread = Thread.new do
|
43
42
|
begin
|
44
43
|
@handler = eval(@config.get(RACK_HANDLER_KEY, DEFAULT_RACK_HANDLER))
|
45
44
|
app = Rack::URLMap.new(get_url_map)
|
46
45
|
app = Rack::CommonLogger.new(app, build_access_logger)
|
47
|
-
|
46
|
+
app = Rack::Rewrite.new(app){
|
47
|
+
# below 4 rules are for backward compatibility
|
48
|
+
r301 %r{^/jobs/?$}, "/"
|
49
|
+
rewrite %r{^/jobs/([^/]+)$}, "/api/v1/jobs/$1"
|
50
|
+
rewrite "/worker", "/api/v1/workers/this/state"
|
51
|
+
rewrite "/worker/status", "/api/v1/workers/this/state"
|
52
|
+
# for web console
|
53
|
+
rewrite %r{^(?!/api)}, "/"
|
54
|
+
}
|
55
|
+
app = Rack::Static.new(app, :urls => ["/js", "/css"], :root => File.join($home, "public"))
|
56
|
+
# TODO set options based on Handler type
|
57
|
+
@handler.run(app, {:Port => @port, :Host => '0.0.0.0', :signals => false}) do |server|
|
58
|
+
server.threaded = true
|
59
|
+
server.threadpool_size = 5
|
60
|
+
server.timeout = 60
|
61
|
+
end
|
48
62
|
rescue => e
|
49
63
|
@logger.error e
|
64
|
+
raise e
|
50
65
|
end
|
51
66
|
end
|
52
|
-
@logger.info "info server has started"
|
67
|
+
@logger.info "info server has started with #{@handler.class}"
|
53
68
|
return true
|
54
69
|
end
|
55
70
|
|
56
71
|
# @return [Hash<String, Sinatra::Base>]
|
57
72
|
def get_url_map
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
"/worker" => Patriot::Worker::Servlet::WorkerStatusServlet}
|
62
|
-
else
|
63
|
-
urlmap = {}
|
64
|
-
urls = [url] unless urls.is_a? Array
|
65
|
-
urls.each do |u|
|
66
|
-
servlet = eval( @config.get("#{URL_MAP_KEY_PREFIX}.#{u}") )
|
67
|
-
u = "/#{u}" unless u.start_with?("/")
|
68
|
-
urlmap[u] = servlet
|
69
|
-
end
|
70
|
-
end
|
73
|
+
urlmap = {"/" => Patriot::Worker::Servlet::IndexServlet,
|
74
|
+
"/api/v1/jobs" => Patriot::Worker::Servlet::JobAPIServlet,
|
75
|
+
"/api/v1/workers" => Patriot::Worker::Servlet::WorkerAPIServlet}
|
71
76
|
urlmap.values.each{|servlet| servlet.configure(@worker, @config)}
|
72
77
|
return urlmap
|
73
78
|
end
|
@@ -82,8 +87,13 @@ module Patriot
|
|
82
87
|
def shutdown_server
|
83
88
|
return false if @server.nil?
|
84
89
|
unless @server_thread.nil?
|
85
|
-
|
86
|
-
|
90
|
+
begin
|
91
|
+
@handler.shutdown
|
92
|
+
@logger.info "info server shutdowned"
|
93
|
+
rescue => e
|
94
|
+
@logger.error "failed to shutdown infoserver", e
|
95
|
+
raise e
|
96
|
+
end
|
87
97
|
end
|
88
98
|
end
|
89
99
|
|
@@ -10,14 +10,10 @@ module Patriot
|
|
10
10
|
# default offset for searching jobs
|
11
11
|
DEFAULT_JOB_OFFSET = 0
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
require 'patriot/worker/servlet/job_servlet.rb'
|
19
|
-
require 'patriot/worker/servlet/worker_status_servlet.rb'
|
20
|
-
|
13
|
+
require 'patriot/worker/servlet/index_servlet.rb'
|
14
|
+
require 'patriot/worker/servlet/api_servlet_base.rb'
|
15
|
+
require 'patriot/worker/servlet/job_api_servlet.rb'
|
16
|
+
require 'patriot/worker/servlet/worker_api_servlet.rb'
|
21
17
|
end
|
22
18
|
end
|
23
19
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'sinatra/base'
|
2
|
+
|
3
|
+
module Patriot
|
4
|
+
module Worker
|
5
|
+
module Servlet
|
6
|
+
class APIServletBase < Sinatra::Base
|
7
|
+
set :show_exceptions, :after_handler
|
8
|
+
|
9
|
+
### Helper Methods
|
10
|
+
helpers do
|
11
|
+
# require authorization for updating
|
12
|
+
def protected!
|
13
|
+
return if authorized?
|
14
|
+
headers['WWW-Authenticate'] = 'Basic Realm="Admin Only"'
|
15
|
+
halt 401, "Not Authorized"
|
16
|
+
end
|
17
|
+
|
18
|
+
# authorize user (basic authentication)
|
19
|
+
def authorized?
|
20
|
+
@auth ||= Rack::Auth::Basic::Request.new(request.env)
|
21
|
+
return @auth.provided? && @auth.basic? && @auth.credentials && @auth.credentials == [@@username, @@password]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# @param worker [Patriot::Wokrer::Base]
|
26
|
+
# @param config [Patriot::Util::Config::Base]
|
27
|
+
def self.configure(worker, config)
|
28
|
+
@@worker = worker
|
29
|
+
@@config = config
|
30
|
+
@@username = config.get(Patriot::Util::Config::USERNAME_KEY, "")
|
31
|
+
@@password = config.get(Patriot::Util::Config::PASSWORD_KEY, "")
|
32
|
+
end
|
33
|
+
|
34
|
+
before do
|
35
|
+
content_type 'application/json;charset=utf8'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'sinatra/base'
|
2
|
+
require 'sinatra/contrib'
|
3
|
+
|
4
|
+
module Patriot
|
5
|
+
module Worker
|
6
|
+
module Servlet
|
7
|
+
|
8
|
+
# allow to monitor worker status
|
9
|
+
class IndexServlet < Sinatra::Base
|
10
|
+
register Sinatra::Contrib
|
11
|
+
|
12
|
+
set :public_folder, File.join($home, "public")
|
13
|
+
set :views, File.join($home, "public", "views")
|
14
|
+
|
15
|
+
# @param worker [Patriot::Worker::Base]
|
16
|
+
# @param config [Patriot::Util::Config::Base]
|
17
|
+
def self.configure(worker, config)
|
18
|
+
@@worker = worker
|
19
|
+
end
|
20
|
+
|
21
|
+
before do
|
22
|
+
@worker = @@worker
|
23
|
+
end
|
24
|
+
|
25
|
+
get '/' do
|
26
|
+
erb :index
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,156 @@
|
|
1
|
+
require 'sinatra/base'
|
2
|
+
require 'sinatra/contrib'
|
3
|
+
|
4
|
+
module Patriot
|
5
|
+
module Worker
|
6
|
+
module Servlet
|
7
|
+
# excepton thrown in case job not found
|
8
|
+
class JobNotFoundException < Exception; end
|
9
|
+
# provide job management functionalities
|
10
|
+
class JobAPIServlet < Patriot::Worker::Servlet::APIServletBase
|
11
|
+
register Sinatra::Contrib
|
12
|
+
include Patriot::Util::DateUtil
|
13
|
+
include Patriot::Command::Parser
|
14
|
+
|
15
|
+
set :show_exceptions, :after_handler
|
16
|
+
|
17
|
+
get '/stats' do
|
18
|
+
return JSON.generate(@@worker.job_store.get_job_size(:ignore_states => [Patriot::JobStore::JobState::SUCCEEDED]))
|
19
|
+
end
|
20
|
+
|
21
|
+
get '/' do
|
22
|
+
state = (params['state'] || Patriot::JobStore::JobState::FAILED).to_i
|
23
|
+
limit = (params['limit'] || DEFAULT_JOB_LIMIT).to_i
|
24
|
+
offset = (params['offset'] || DEFAULT_JOB_OFFSET).to_i
|
25
|
+
|
26
|
+
query = {:limit => limit, :offset => offset}
|
27
|
+
query[:filter_exp] = params['filter_exp'] unless params['filter_exp'].blank?
|
28
|
+
job_ids = @@worker.job_store.find_jobs_by_state(state, query) || []
|
29
|
+
return JSON.generate(job_ids.map{|job_id| {:job_id => job_id, :state => state}})
|
30
|
+
end
|
31
|
+
|
32
|
+
get '/:job_id' do
|
33
|
+
job_id = params[:job_id]
|
34
|
+
job = @@worker.job_store.get(job_id, {:include_dependency => true})
|
35
|
+
halt(404, json({ERROR: "Job #{job_id} not found"})) if job.nil?
|
36
|
+
return JSON.generate(job.attributes.merge({'job_id' => job_id, "update_id" => job.update_id}))
|
37
|
+
end
|
38
|
+
|
39
|
+
get '/:job_id/histories' do
|
40
|
+
job_id = params[:job_id]
|
41
|
+
history_size = params['size'] || 3
|
42
|
+
histories = @@worker.job_store.get_execution_history(job_id, {:limit => history_size})
|
43
|
+
return JSON.generate(histories)
|
44
|
+
end
|
45
|
+
|
46
|
+
# get dependency graph of the specified job
|
47
|
+
#
|
48
|
+
# @param [String] job_id
|
49
|
+
# @param [String] p_level a max number of producer dependency level to get
|
50
|
+
# @param [String] c_level a max number of consumer dependency level to get
|
51
|
+
get '/:job_id/graph' do
|
52
|
+
job_id = params[:job_id]
|
53
|
+
producer_depth = (params['p_depth'] || 2).to_i
|
54
|
+
consumer_depth = (params['c_depth'] || 2).to_i
|
55
|
+
graph = @@worker.job_store.get_graph(job_id, {:producer_depth => producer_depth, :consumer_depth => consumer_depth})
|
56
|
+
return JSON.generate(graph)
|
57
|
+
end
|
58
|
+
|
59
|
+
post '/' do
|
60
|
+
protected!
|
61
|
+
body = JSON.parse(request.body.read)
|
62
|
+
halt(400, json({ERROR: "COMMAND_CLASS is not provided"})) if body["COMMAND_CLASS"].blank?
|
63
|
+
halt(400, json({ERROR: "Patriot::Command::CommandGroup is not acceptable"})) if body["COMMAND_CLASS"] == "Patriot::Command::CommandGroup"
|
64
|
+
command_class = body.delete("COMMAND_CLASS").gsub(/\./, '::').constantize
|
65
|
+
|
66
|
+
job = _build_command(command_class, body)[0]
|
67
|
+
job[Patriot::Command::STATE_ATTR] ||= body["state"]
|
68
|
+
@@worker.job_store.register(Time.now.to_i, [job])
|
69
|
+
return JSON.generate({:job_id => job.job_id})
|
70
|
+
end
|
71
|
+
|
72
|
+
put '/' do
|
73
|
+
protected!
|
74
|
+
body = JSON.parse(request.body.read)
|
75
|
+
job_ids = body["job_ids"]
|
76
|
+
state = body['state']
|
77
|
+
_set_state_of_jobs(job_ids, state)
|
78
|
+
return JSON.generate(job_ids.map{|job_id| {"job_id" => job_id, "state" => state} })
|
79
|
+
end
|
80
|
+
|
81
|
+
put '/:job_id' do
|
82
|
+
protected!
|
83
|
+
job_id = params['job_id']
|
84
|
+
job = @@worker.job_store.get(job_id)
|
85
|
+
halt(404, json({ERROR: "Job #{job_id} not found"})) if job.nil?
|
86
|
+
|
87
|
+
body = JSON.parse(request.body.read)
|
88
|
+
state = body['state']
|
89
|
+
options = body['option'] || {}
|
90
|
+
job_ids = _set_state_of_jobs(job_id, state, options)
|
91
|
+
return JSON.generate(job_ids.map{|jid| {"job_id" => jid, "state" => state}})
|
92
|
+
end
|
93
|
+
|
94
|
+
delete '/' do
|
95
|
+
protected!
|
96
|
+
body = request.body.read
|
97
|
+
job_ids = []
|
98
|
+
if body != ''
|
99
|
+
body = JSON.parse(body)
|
100
|
+
job_ids = body["job_ids"]
|
101
|
+
else
|
102
|
+
job_ids = JSON.parse(params["job_ids"])
|
103
|
+
end
|
104
|
+
job_ids.each{ |job_id| @@worker.job_store.delete_job(job_id) }
|
105
|
+
return JSON.generate(job_ids.map{|job_id| {"job_id" => job_id} })
|
106
|
+
end
|
107
|
+
|
108
|
+
delete '/:job_id' do
|
109
|
+
protected!
|
110
|
+
job_id = params['job_id']
|
111
|
+
job = @@worker.job_store.get(job_id)
|
112
|
+
halt(404, json({ERROR: "Job #{job_id} not found"})) if job.nil?
|
113
|
+
|
114
|
+
@@worker.job_store.delete_job(job_id)
|
115
|
+
return JSON.generate({"job_id" => job_id})
|
116
|
+
end
|
117
|
+
|
118
|
+
error JobNotFoundException do
|
119
|
+
"Job #{env['sinatra.error'].message} is not found"
|
120
|
+
end
|
121
|
+
|
122
|
+
# @private
|
123
|
+
def _set_state_of_jobs(job_ids, state, opts = {})
|
124
|
+
job_ids = [job_ids] unless job_ids.is_a? Array
|
125
|
+
opts = {'with_subsequent' => false}.merge(opts)
|
126
|
+
opts = {:include_subsequent => false}.merge(opts)
|
127
|
+
update_id = Time.now.to_i
|
128
|
+
@@worker.job_store.set_state(update_id, job_ids, state)
|
129
|
+
if opts['with_subsequent']
|
130
|
+
@@worker.job_store.process_subsequent(job_ids) do |job_store, jobs|
|
131
|
+
next if jobs.empty?
|
132
|
+
subsequent_ids = jobs.map(&:job_id)
|
133
|
+
@@worker.job_store.set_state(update_id, subsequent_ids, state)
|
134
|
+
job_ids |= subsequent_ids
|
135
|
+
end
|
136
|
+
end
|
137
|
+
return job_ids.uniq
|
138
|
+
end
|
139
|
+
private :_set_state_of_jobs
|
140
|
+
|
141
|
+
# @private
|
142
|
+
def _build_command(clazz, params)
|
143
|
+
_params = params.dup
|
144
|
+
_params["target_datetime"] = Date.today
|
145
|
+
cmd = clazz.new(@@config)
|
146
|
+
cmd.produce(_params.delete("products")) unless _params["products"].nil?
|
147
|
+
cmd.require(_params.delete("requisites")) unless _params["requisites"].nil?
|
148
|
+
cmds = cmd.build(_params)
|
149
|
+
return cmds.map{|c| c.to_job}
|
150
|
+
end
|
151
|
+
private :_build_command
|
152
|
+
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'sinatra/base'
|
2
|
+
require 'sinatra/contrib'
|
3
|
+
|
4
|
+
module Patriot
|
5
|
+
module Worker
|
6
|
+
module Servlet
|
7
|
+
# excepton thrown when a woker is not accessible
|
8
|
+
class WorkerInaccessibleException < Exception; end
|
9
|
+
# provide worker management functionalities
|
10
|
+
class WorkerAPIServlet < Patriot::Worker::Servlet::APIServletBase
|
11
|
+
register Sinatra::Contrib
|
12
|
+
|
13
|
+
HOST_KEY = "host"
|
14
|
+
VERSION_KEY = "version"
|
15
|
+
CLASS_KEY = "class"
|
16
|
+
STARTED_AT_KEY = "started_at"
|
17
|
+
CONFIG_KEY = "config"
|
18
|
+
|
19
|
+
STATE_KEY = "state"
|
20
|
+
|
21
|
+
LOCALHOST_EXPS = ["localhost", "127.0.0.1"]
|
22
|
+
|
23
|
+
set :show_exceptions, :after_handler
|
24
|
+
|
25
|
+
get '/' do
|
26
|
+
worker_hosts = @@config.get(Patriot::Util::Config::WORKER_HOST_KEY)
|
27
|
+
worker_hosts = [worker_hosts] unless worker_hosts.is_a?(Array)
|
28
|
+
worker_hosts = @@config.get(Patriot::Util::Config::WORKER_HOST_KEY).map do |h|
|
29
|
+
h = h.split(":")
|
30
|
+
port = h.size == 2 ? h[1] : Patriot::Worker::InfoServer::DEFAULT_PORT
|
31
|
+
{'host' => h[0], 'port' => port}
|
32
|
+
end
|
33
|
+
return JSON.generate(worker_hosts)
|
34
|
+
end
|
35
|
+
|
36
|
+
get '/this' do
|
37
|
+
return JSON.generate(
|
38
|
+
STATE_KEY => @@worker.status,
|
39
|
+
HOST_KEY => @@worker.host,
|
40
|
+
VERSION_KEY => Patriot::VERSION,
|
41
|
+
CLASS_KEY => @@worker.class.to_s,
|
42
|
+
STARTED_AT_KEY => @@worker.started_at,
|
43
|
+
CONFIG_KEY => {} # TODO
|
44
|
+
)
|
45
|
+
end
|
46
|
+
|
47
|
+
get '/this/state' do
|
48
|
+
return JSON.generate(
|
49
|
+
STATE_KEY => @@worker.status
|
50
|
+
)
|
51
|
+
end
|
52
|
+
|
53
|
+
put '/this/state' do
|
54
|
+
protected!
|
55
|
+
new_status = params['status']
|
56
|
+
if [Patriot::Worker::Status::ACTIVE, Patriot::Worker::Status::SLEEP ].include?(@@worker.status)
|
57
|
+
@@worker.status = new_status
|
58
|
+
else
|
59
|
+
# state cannot be changed in shutdown process
|
60
|
+
halt 403
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|