patriot-workflow-scheduler 0.6.1
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 +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
|