patriot-workflow-scheduler 0.6.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/bin/patriot +8 -0
- data/bin/patriot-init +35 -0
- data/lib/patriot.rb +11 -0
- data/lib/patriot/command.rb +71 -0
- data/lib/patriot/command/base.rb +199 -0
- data/lib/patriot/command/command_group.rb +43 -0
- data/lib/patriot/command/command_macro.rb +141 -0
- data/lib/patriot/command/composite.rb +49 -0
- data/lib/patriot/command/parser.rb +78 -0
- data/lib/patriot/command/sh_command.rb +42 -0
- data/lib/patriot/controller.rb +2 -0
- data/lib/patriot/controller/package_controller.rb +81 -0
- data/lib/patriot/controller/worker_admin_controller.rb +159 -0
- data/lib/patriot/job_store.rb +66 -0
- data/lib/patriot/job_store/base.rb +159 -0
- data/lib/patriot/job_store/factory.rb +19 -0
- data/lib/patriot/job_store/in_memory_store.rb +252 -0
- data/lib/patriot/job_store/job.rb +118 -0
- data/lib/patriot/job_store/job_ticket.rb +30 -0
- data/lib/patriot/job_store/rdb_job_store.rb +353 -0
- data/lib/patriot/tool.rb +2 -0
- data/lib/patriot/tool/batch_parser.rb +102 -0
- data/lib/patriot/tool/patriot_command.rb +48 -0
- data/lib/patriot/tool/patriot_commands/execute.rb +92 -0
- data/lib/patriot/tool/patriot_commands/job.rb +62 -0
- data/lib/patriot/tool/patriot_commands/plugin.rb +41 -0
- data/lib/patriot/tool/patriot_commands/register.rb +77 -0
- data/lib/patriot/tool/patriot_commands/upgrade.rb +24 -0
- data/lib/patriot/tool/patriot_commands/validate.rb +84 -0
- data/lib/patriot/tool/patriot_commands/worker.rb +35 -0
- data/lib/patriot/tool/patriot_commands/worker_admin.rb +60 -0
- data/lib/patriot/util.rb +14 -0
- data/lib/patriot/util/config.rb +58 -0
- data/lib/patriot/util/config/base.rb +22 -0
- data/lib/patriot/util/config/inifile_config.rb +63 -0
- data/lib/patriot/util/cron_format_parser.rb +104 -0
- data/lib/patriot/util/date_util.rb +200 -0
- data/lib/patriot/util/db_client.rb +65 -0
- data/lib/patriot/util/db_client/base.rb +142 -0
- data/lib/patriot/util/db_client/hash_record.rb +53 -0
- data/lib/patriot/util/db_client/record.rb +25 -0
- data/lib/patriot/util/logger.rb +24 -0
- data/lib/patriot/util/logger/facade.rb +33 -0
- data/lib/patriot/util/logger/factory.rb +59 -0
- data/lib/patriot/util/logger/log4r_factory.rb +111 -0
- data/lib/patriot/util/logger/webrick_log_factory.rb +47 -0
- data/lib/patriot/util/param.rb +73 -0
- data/lib/patriot/util/retry.rb +30 -0
- data/lib/patriot/util/script.rb +52 -0
- data/lib/patriot/util/system.rb +120 -0
- data/lib/patriot/worker.rb +35 -0
- data/lib/patriot/worker/base.rb +153 -0
- data/lib/patriot/worker/info_server.rb +90 -0
- data/lib/patriot/worker/job_store_server.rb +32 -0
- data/lib/patriot/worker/multi_node_worker.rb +157 -0
- data/lib/patriot/worker/servlet.rb +23 -0
- data/lib/patriot/worker/servlet/job_servlet.rb +128 -0
- data/lib/patriot/worker/servlet/worker_status_servlet.rb +44 -0
- data/skel/batch/sample/daily/test.pbc +4 -0
- data/skel/config/patriot.ini +21 -0
- data/skel/public/css/bootstrap.css +2495 -0
- data/skel/public/css/original.css +54 -0
- data/skel/public/js/bootstrap-alerts.js +124 -0
- data/skel/public/js/bootstrap-buttons.js +64 -0
- data/skel/public/js/bootstrap-dropdown.js +55 -0
- data/skel/public/js/bootstrap-modal.js +260 -0
- data/skel/public/js/bootstrap-popover.js +90 -0
- data/skel/public/js/bootstrap-scrollspy.js +107 -0
- data/skel/public/js/bootstrap-tabs.js +80 -0
- data/skel/public/js/bootstrap-twipsy.js +321 -0
- data/skel/public/js/jquery-1.6.4.min.js +4 -0
- data/skel/public/templates/_jobs.erb +97 -0
- data/skel/public/templates/job.erb +119 -0
- data/skel/public/templates/jobs.erb +21 -0
- data/skel/public/templates/jobs_deleted.erb +6 -0
- data/skel/public/templates/layout.erb +103 -0
- data/skel/public/templates/state_updated.erb +6 -0
- metadata +235 -0
@@ -0,0 +1,90 @@
|
|
1
|
+
module Patriot
|
2
|
+
module Worker
|
3
|
+
# info server (web management console and for monitoring)
|
4
|
+
class InfoServer
|
5
|
+
|
6
|
+
# configuratio key for port used by this server
|
7
|
+
PORT_KEY = 'info_server.port'
|
8
|
+
# default port number
|
9
|
+
DEFAULT_PORT = '36104'
|
10
|
+
|
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
|
+
# configuration key for rack handler used to start this server
|
17
|
+
RACK_HANDLER_KEY = 'info_server.rack.handler'
|
18
|
+
# default rack handler
|
19
|
+
DEFAULT_RACK_HANDLER = 'Rack::Handler::WEBrick'
|
20
|
+
|
21
|
+
include Patriot::Util::Config
|
22
|
+
include Patriot::Util::Logger
|
23
|
+
|
24
|
+
# @param worker [Patriot::Worker::Base] worker managed through this server
|
25
|
+
# @param config [Patriot::Util::Config::Bae]
|
26
|
+
def initialize(worker, config)
|
27
|
+
@logger = create_logger(config)
|
28
|
+
@worker = worker
|
29
|
+
@config = config
|
30
|
+
end
|
31
|
+
|
32
|
+
# start the server
|
33
|
+
def start_server
|
34
|
+
port = @config.get(Patriot::Worker::InfoServer::PORT_KEY,
|
35
|
+
Patriot::Worker::InfoServer::DEFAULT_PORT)
|
36
|
+
if port.nil?
|
37
|
+
@logger.info("port is not set. starting info server is skipped")
|
38
|
+
return
|
39
|
+
end
|
40
|
+
@server_thread = Thread.new do
|
41
|
+
begin
|
42
|
+
@handler = eval(@config.get(RACK_HANDLER_KEY, DEFAULT_RACK_HANDLER))
|
43
|
+
app = Rack::URLMap.new(get_url_map)
|
44
|
+
app = Rack::CommonLogger.new(app, build_access_logger)
|
45
|
+
@handler.run app, {:Port => port, :Host => '0.0.0.0'}
|
46
|
+
rescue => e
|
47
|
+
@logger.error e
|
48
|
+
end
|
49
|
+
end
|
50
|
+
@logger.info "info server has started"
|
51
|
+
return true
|
52
|
+
end
|
53
|
+
|
54
|
+
# @return [Hash<String, Sinatra::Base>]
|
55
|
+
def get_url_map
|
56
|
+
urls = @config.get(URLS_KEY, nil)
|
57
|
+
if urls.nil?
|
58
|
+
urlmap = {"/jobs" => Patriot::Worker::Servlet::JobServlet,
|
59
|
+
"/worker" => Patriot::Worker::Servlet::WorkerStatusServlet}
|
60
|
+
else
|
61
|
+
urlmap = {}
|
62
|
+
urls = [url] unless urls.is_a? Array
|
63
|
+
urls.each do |u|
|
64
|
+
servlet = eval( @config.get("#{URL_MAP_KEY_PREFIX}.#{u}") )
|
65
|
+
u = "/#{u}" unless u.start_with?("/")
|
66
|
+
urlmap[u] = servlet
|
67
|
+
end
|
68
|
+
end
|
69
|
+
urlmap.values.each{|servlet| servlet.configure(@worker, @config)}
|
70
|
+
return urlmap
|
71
|
+
end
|
72
|
+
|
73
|
+
def build_access_logger
|
74
|
+
config = load_config(:path => @config.path, :type => 'web', :ignore_plugin => true)
|
75
|
+
return Patriot::Util::Logger::Factory.create_logger(@hanlder.class.to_s, config)
|
76
|
+
end
|
77
|
+
private :build_access_logger
|
78
|
+
|
79
|
+
# instruct to shutdown server
|
80
|
+
def shutdown_server
|
81
|
+
return false if @server.nil?
|
82
|
+
unless @server_thread.nil?
|
83
|
+
@handler.shutdown
|
84
|
+
@logger.info "info server shutdowned"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'thread'
|
2
|
+
require 'monitor'
|
3
|
+
|
4
|
+
module Patriot
|
5
|
+
module Worker
|
6
|
+
# a worker as info server
|
7
|
+
class JobStoreServer < Base
|
8
|
+
|
9
|
+
# @see Patriot::Worker::Base#build_infoserver
|
10
|
+
def build_infoserver
|
11
|
+
return Patriot::Worker::InfoServer.new(self,@config)
|
12
|
+
end
|
13
|
+
|
14
|
+
# @see Patriot::Worker::Base#init_worker
|
15
|
+
def init_worker
|
16
|
+
end
|
17
|
+
|
18
|
+
# @see Patriot::Worker::Base#run_worker
|
19
|
+
def run_worker
|
20
|
+
while(@status != Patriot::Worker::Status::SHUTDOWN)
|
21
|
+
sleep @cycle
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# @see Patriot::Worker::Base#stop_worker
|
26
|
+
def stop_worker
|
27
|
+
@logger.info "terminated"
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,157 @@
|
|
1
|
+
require 'thread'
|
2
|
+
require 'monitor'
|
3
|
+
|
4
|
+
module Patriot
|
5
|
+
module Worker
|
6
|
+
|
7
|
+
# a worker implementation which can host multiple node on one process
|
8
|
+
class MultiNodeWorker < Base
|
9
|
+
|
10
|
+
include MonitorMixin
|
11
|
+
|
12
|
+
### type of node
|
13
|
+
# handle any jobs without label or same label
|
14
|
+
ANY = 'any'
|
15
|
+
# handle only jobs with same label
|
16
|
+
OWN = 'own'
|
17
|
+
# supporte node types
|
18
|
+
SUPPORTED_TYPES = [ANY,OWN]
|
19
|
+
|
20
|
+
### type of job
|
21
|
+
# executed by any node
|
22
|
+
ANY_EXCLUDE_TYPE_OWN = 0
|
23
|
+
# executed by only same labeled node
|
24
|
+
ONLY_SPECIFIED_NODE = 1
|
25
|
+
# unknown
|
26
|
+
UNEXPECTED = 2
|
27
|
+
|
28
|
+
# @see Patriot::Worker::Base#init_worker
|
29
|
+
def init_worker
|
30
|
+
nodes = @config.get('nodes')
|
31
|
+
raise "nodes are not configured" if nodes.nil?
|
32
|
+
nodes = [nodes] unless nodes.is_a?(Array)
|
33
|
+
@nodes = {}
|
34
|
+
nodes.each do |n|
|
35
|
+
node_config = get_node_config(@config, n)
|
36
|
+
raise "node #{n} is not configured" if node_config.nil?
|
37
|
+
@nodes[n] = {:queue => Queue.new }.merge(node_config)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def get_node_config(config, n)
|
42
|
+
type = config.get("node.#{n}.type")
|
43
|
+
threads = config.get("node.#{n}.threads")
|
44
|
+
raise "the number of threads for node #{n} is not set" if threads.nil?
|
45
|
+
raise "unsupported node type: #{n} with #{type} " unless SUPPORTED_TYPES.include?(type)
|
46
|
+
return {:type => type, :threads => threads.to_i}
|
47
|
+
end
|
48
|
+
private :get_node_config
|
49
|
+
|
50
|
+
# @see Patriot::Worker::Base#run_worker
|
51
|
+
def run_worker
|
52
|
+
@threads = []
|
53
|
+
# create node threads for job execution
|
54
|
+
@nodes.each do |node,conf|
|
55
|
+
1.upto(conf[:threads]) do |i|
|
56
|
+
@threads << create_thread(node, i, conf[:queue])
|
57
|
+
end
|
58
|
+
end
|
59
|
+
# start main thread for updating queues
|
60
|
+
Thread.current[:name] = 'main'
|
61
|
+
while(alive?)
|
62
|
+
if @status == Patriot::Worker::Status::ACTIVE
|
63
|
+
begin
|
64
|
+
job_tickets = @job_store.get_job_tickets(@host, @nodes.keys, {:fetch_limit => @fetch_limit})
|
65
|
+
@logger.info "get #{job_tickets.size} jobs"
|
66
|
+
update_queue(job_tickets) unless job_tickets.nil?
|
67
|
+
rescue => e
|
68
|
+
@logger.error e
|
69
|
+
end
|
70
|
+
end
|
71
|
+
sleep @cycle
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def create_thread(node, thread_number, queue)
|
76
|
+
Thread.start(queue) do |q|
|
77
|
+
Thread.current[:name] = "worker_#{node}_#{thread_number}"
|
78
|
+
Thread.current[:node] = node
|
79
|
+
begin
|
80
|
+
while(@status != Patriot::Worker::Status::SHUTDOWN)
|
81
|
+
job_ticket = q.pop
|
82
|
+
if job_ticket == :TERM
|
83
|
+
@logger.info "terminating"
|
84
|
+
else
|
85
|
+
@logger.debug "fetch job #{job_ticket.job_id}"
|
86
|
+
Thread.current[Patriot::Worker::JOB_ID_IN_EXECUTION] = job_ticket.job_id
|
87
|
+
execute_job(job_ticket)
|
88
|
+
Thread.current[Patriot::Worker::JOB_ID_IN_EXECUTION] = nil
|
89
|
+
end
|
90
|
+
end
|
91
|
+
rescue Exception => e
|
92
|
+
@logger.error e
|
93
|
+
raise e, "exception in worker thread" , $@
|
94
|
+
ensure
|
95
|
+
@logger.info "terminated"
|
96
|
+
interrupted_job = Thread.current[Patriot::Worker::JOB_ID_IN_EXECUTION]
|
97
|
+
@logger.warn "job: #{interrupted_job} could be interrupted." unless interrupted_job.nil?
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
private :create_thread
|
102
|
+
|
103
|
+
# check thread status
|
104
|
+
def alive?
|
105
|
+
@threads.each do |t|
|
106
|
+
if t.status.nil? # thread stopped by some error
|
107
|
+
@logger.error "#{t[:name]} : nil "
|
108
|
+
@status = Patriot::Worker::Status::SHUTDOWN
|
109
|
+
elsif t.status == false # stopped by signal
|
110
|
+
@logger.debug "#{t[:name]} : false "
|
111
|
+
@status = Patriot::Worker::Status::SHUTDOWN
|
112
|
+
else
|
113
|
+
@logger.debug "#{t[:name]} : #{t.status}"
|
114
|
+
end
|
115
|
+
end
|
116
|
+
return @status != Patriot::Worker::Status::SHUTDOWN
|
117
|
+
end
|
118
|
+
private :alive?
|
119
|
+
|
120
|
+
# update job queues
|
121
|
+
def update_queue(job_tickets)
|
122
|
+
@nodes.each{|node,conf| conf[:queue].clear }
|
123
|
+
job_tickets.each do |job_ticket|
|
124
|
+
case type_of_job(job_ticket)
|
125
|
+
when ANY_EXCLUDE_TYPE_OWN
|
126
|
+
@nodes.each{|node,conf| conf[:queue].push(job_ticket) unless conf[:type]==OWN }
|
127
|
+
when ONLY_SPECIFIED_NODE
|
128
|
+
@nodes[job_ticket.node][:queue].push(job_ticket)
|
129
|
+
else
|
130
|
+
@logger.warn "receive unexpected job #{job_ticket.to_s}"
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
private :update_queue
|
135
|
+
|
136
|
+
def type_of_job(job_ticket)
|
137
|
+
return ANY_EXCLUDE_TYPE_OWN if job_ticket.node.nil?
|
138
|
+
return ONLY_SPECIFIED_NODE if @nodes.has_key?(job_ticket.node)
|
139
|
+
return UNEXPECTED;
|
140
|
+
end
|
141
|
+
private :type_of_job
|
142
|
+
|
143
|
+
# @see Patriot::Worker::Base#run_worker
|
144
|
+
def stop_worker
|
145
|
+
@status = Patriot::Worker::Status::SHUTDOWN
|
146
|
+
@logger.info "terminating worker"
|
147
|
+
@nodes.each do |node,conf|
|
148
|
+
conf[:queue].clear
|
149
|
+
1.upto(conf[:threads]) {|i| conf[:queue].push(:TERM) }
|
150
|
+
end
|
151
|
+
@threads.each{|t| t.join}
|
152
|
+
@logger.info "terminated"
|
153
|
+
end
|
154
|
+
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'sinatra/base'
|
2
|
+
require 'sinatra/contrib'
|
3
|
+
|
4
|
+
module Patriot
|
5
|
+
module Worker
|
6
|
+
# namespacce infoserve servlet
|
7
|
+
module Servlet
|
8
|
+
# default limit in searching jobs
|
9
|
+
DEFAULT_JOB_LIMIT = 50
|
10
|
+
# default offset for searching jobs
|
11
|
+
DEFAULT_JOB_OFFSET = 0
|
12
|
+
|
13
|
+
# configuratio key for admin user name
|
14
|
+
USERNAME_KEY = 'info_server.admin.username'
|
15
|
+
# configuratio key for admin password
|
16
|
+
PASSWORD_KEY = 'info_server.admin.password'
|
17
|
+
|
18
|
+
require 'patriot/worker/servlet/job_servlet.rb'
|
19
|
+
require 'patriot/worker/servlet/worker_status_servlet.rb'
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,128 @@
|
|
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 JobServlet < Sinatra::Base
|
11
|
+
register Sinatra::Contrib
|
12
|
+
|
13
|
+
set :public_folder, File.join($home, "public")
|
14
|
+
set :views, File.join($home, "public", "templates")
|
15
|
+
set :show_exceptions, :after_handler
|
16
|
+
|
17
|
+
# @param worker [Patriot::Wokrer::Base]
|
18
|
+
# @param config [Patriot::Util::Config::Base]
|
19
|
+
def self.configure(worker, config)
|
20
|
+
@@job_store = worker.job_store
|
21
|
+
@@username = config.get(USERNAME_KEY, "")
|
22
|
+
@@password = config.get(PASSWORD_KEY, "")
|
23
|
+
end
|
24
|
+
|
25
|
+
### Helper Methods
|
26
|
+
helpers do
|
27
|
+
# return link to each job information
|
28
|
+
def to_job_link(job_id)
|
29
|
+
return "<a href='/jobs/#{ERB::Util.url_encode(job_id)}'>#{job_id}</a>"
|
30
|
+
end
|
31
|
+
# require authorization for updating
|
32
|
+
def protected!
|
33
|
+
return if authorized?
|
34
|
+
headers['WWW-Authenticate'] = 'Basic Realm="Admin Only"'
|
35
|
+
halt 401, "Not Authorized"
|
36
|
+
end
|
37
|
+
# authorize user (basic authentication)
|
38
|
+
def authorized?
|
39
|
+
@auth ||= Rack::Auth::Basic::Request.new(request.env)
|
40
|
+
return @auth.provided? && @auth.basic? && @auth.credentials && @auth.credentials == [@@username, @@password]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
get '/' do
|
45
|
+
state = params['state'] || Patriot::JobStore::JobState::FAILED
|
46
|
+
update_job_size(state)
|
47
|
+
query = {:limit => params['limit'] || DEFAULT_JOB_LIMIT,
|
48
|
+
:offset => params['offset'] || DEFAULT_JOB_OFFSET}
|
49
|
+
query[:filter_exp] = params['filter_exp'] if params.has_key?('filter_exp') && params['filter_exp'] != ""
|
50
|
+
jobs = @@job_store.find_jobs_by_state(state.to_i, query)
|
51
|
+
jobs ||= []
|
52
|
+
respond_with :jobs, {:jobs => jobs, :state => state, :filter_exp => query[:filter_exp]}.merge(query)
|
53
|
+
end
|
54
|
+
|
55
|
+
post '/' do
|
56
|
+
protected!
|
57
|
+
job_ids = params['job_ids']
|
58
|
+
if params['_method'] == 'put'
|
59
|
+
state = params['state']
|
60
|
+
set_state_of_jobs(job_ids, state)
|
61
|
+
elsif params['_method'] == 'delete'
|
62
|
+
delete_jobs(job_ids)
|
63
|
+
else
|
64
|
+
raise NotImplementedError
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
get '/:job_id' do
|
69
|
+
job_id = params[:job_id]
|
70
|
+
history_size = params['history_size'] || 1
|
71
|
+
job = @@job_store.get(job_id, {:include_dependency => true})
|
72
|
+
raise JobNotFoundException, job_id if job.nil?
|
73
|
+
update_job_size(job[Patriot::Command::STATE_ATTR])
|
74
|
+
histories = @@job_store.get_execution_history(job_id, {:limit => history_size})
|
75
|
+
# respond_with :job, {:job => job, :histories => histories}
|
76
|
+
respond_to do |f|
|
77
|
+
f.on('text/html'){ erb :job, :locals => {:job => job, :histories => histories} }
|
78
|
+
# for monitoring
|
79
|
+
f.on('*/*'){ JSON.generate(job.attributes.merge({'job_id' => job_id})) }
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
post '/:job_id' do
|
84
|
+
protected!
|
85
|
+
if params['_method'] == 'put'
|
86
|
+
set_state_of_jobs([params['job_id']], params['state'], {:include_subsequent => params['include_subsequent'] == 'true'})
|
87
|
+
respond_with :state_updated, {:jobs => job_ids, :state => state}
|
88
|
+
else
|
89
|
+
raise NotImplementedError
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
error JobNotFoundException do
|
94
|
+
"Job #{env['sinatra.error'].message} is not found"
|
95
|
+
end
|
96
|
+
|
97
|
+
# update jobs size
|
98
|
+
def update_job_size(state)
|
99
|
+
@size = @@job_store.get_job_size(:ignore_states => [Patriot::JobStore::JobState::SUCCEEDED])
|
100
|
+
end
|
101
|
+
|
102
|
+
# @private
|
103
|
+
# update state of jobs
|
104
|
+
def set_state_of_jobs(job_ids, state, opts = {})
|
105
|
+
opts = {:include_subsequent => false}.merge(opts)
|
106
|
+
update_id = Time.now.to_i
|
107
|
+
@@job_store.set_state(update_id, job_ids, state)
|
108
|
+
if opts[:include_subsequent]
|
109
|
+
@@job_store.process_subsequent(job_ids) do |job_store, jobs|
|
110
|
+
@@job_store.set_state(update_id, jobs.map(&:job_id), state)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
update_job_size(state)
|
114
|
+
respond_with :state_updated, {:jobs => job_ids, :state => state}
|
115
|
+
end
|
116
|
+
private :set_state_of_jobs
|
117
|
+
|
118
|
+
def delete_jobs(job_ids)
|
119
|
+
job_ids.each{|jid| @@job_store.delete_job(jid) }
|
120
|
+
update_job_size(Patriot::JobStore::JobState::DISCARDED)
|
121
|
+
respond_with :jobs_deleted, {:jobs => job_ids}
|
122
|
+
end
|
123
|
+
private :delete_jobs
|
124
|
+
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
@@ -0,0 +1,44 @@
|
|
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 WorkerStatusServlet < Sinatra::Base
|
10
|
+
register Sinatra::Contrib
|
11
|
+
|
12
|
+
set :public_folder, File.join($home, "public")
|
13
|
+
set :views, File.join($home, "public", "templates")
|
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
|
+
respond_with :worker, {:worker => @worker} do |f|
|
27
|
+
# for monitoring
|
28
|
+
f.on('*/*') { JSON.generate(@worker.host => @worker.status)}
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
put '/' do
|
33
|
+
new_status = params['status']
|
34
|
+
if [Patriot::Worker::Status::ACTIVE, Patriot::Worker::Status::SLEEP ]
|
35
|
+
@worker.status = new_status
|
36
|
+
else
|
37
|
+
return 400
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|