Skip to content

Commit 639f950

Browse files
committed
Worker group dashboard + misc fixes
1 parent 57800f8 commit 639f950

8 files changed

Lines changed: 106 additions & 11 deletions

File tree

mrq/agent.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from .context import get_current_config, connections, log
44
import time
5-
import json
5+
import datetime
66
import gevent
77
from bson import ObjectId
88
from collections import defaultdict
@@ -33,6 +33,8 @@ def work(self):
3333

3434
self.pool.wait()
3535

36+
connections.mongodb_jobs.mrq_agents.delete_one({"_id": self.id})
37+
3638
def shutdown_now(self):
3739
self.pool.terminate()
3840

@@ -78,7 +80,8 @@ def get_agent_report(self):
7880
"current_workers": [p["command"] for p in self.pool.processes],
7981
"available_cpu": get_current_config()["available_cpu"],
8082
"available_memory": get_current_config()["available_memory"],
81-
"worker_group": self.worker_group
83+
"worker_group": self.worker_group,
84+
8285
}
8386
return report
8487

@@ -181,7 +184,8 @@ def orchestrate(self):
181184
connections.mongodb_jobs.mrq_agents.update_one({"_id": agent["_id"]}, {"$set": {
182185
"desired_workers": agent["new_desired_workers"],
183186
"free_cpu": agent["free_cpu"],
184-
"free_memory": agent["free_memory"]
187+
"free_memory": agent["free_memory"],
188+
"datereported": datetime.datetime.utcnow()
185189
}})
186190

187191
def get_desired_workers_for_group(self, group):

mrq/dashboard/app.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import json
1616
import argparse
1717
from werkzeug.serving import run_simple
18+
from future.builtins import str
1819

1920
sys.path.insert(0, os.getcwd())
2021

@@ -122,6 +123,24 @@ def get_workers():
122123
return jsonify(data)
123124

124125

126+
@app.route('/api/workergroups', methods=["GET"])
127+
@requires_auth
128+
def get_workergroups():
129+
collection = connections.mongodb_jobs.mrq_workergroups
130+
data = {"workergroups": {str(row.pop("_id")): row for row in collection.find(sort=[("_id", 1)])}}
131+
return jsonify(data)
132+
133+
134+
@app.route('/api/workergroups', methods=["POST"])
135+
@requires_auth
136+
def post_workergroups():
137+
workergroups = json.loads(request.form["workergroups"])
138+
for k, v in workergroups.iteritems():
139+
connections.mongodb_jobs.mrq_workergroups.update_one({"_id": k}, {"$set": v}, upsert=True)
140+
141+
return jsonify({"status": "ok"})
142+
143+
125144
def build_api_datatables_query(req):
126145
query = {}
127146

mrq/dashboard/static/js/router.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ define(["backbone", "underscore", "jquery"],function(Backbone, _, $) {
1212
'jobs': 'jobs',
1313
'io': 'io',
1414
'scheduledjobs': 'scheduledjobs',
15-
'status': 'status'
15+
'status': 'status',
16+
'workergroups': 'workergroups'
1617
},
1718

1819
/**
@@ -125,6 +126,11 @@ define(["backbone", "underscore", "jquery"],function(Backbone, _, $) {
125126
this.app.rootView.showChildPage('io', {"options": {"params": params || {}}});
126127
},
127128

129+
workergroups: function(params) {
130+
this.setNavbar("workergroups");
131+
this.app.rootView.showChildPage('workergroups', {"options": {"params": params || {}}});
132+
},
133+
128134
taskpaths: function(params) {
129135
this.setNavbar("taskpaths");
130136
this.app.rootView.showChildPage('taskpaths', {"options": {"params": params || {}}});

mrq/dashboard/static/js/views/root.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22
* @fileoverview Defines the view container view that contains all views
33
*/
44
define(["views/generic/page", "jquery",
5-
"views/queues", "views/workers", "views/jobs", "views/scheduledjobs", "views/index", "views/taskpaths", "views/status", "views/taskexceptions", "views/io"],
5+
"views/queues", "views/workers", "views/jobs", "views/scheduledjobs", "views/index", "views/taskpaths", "views/status", "views/taskexceptions", "views/io", "views/workergroups"],
66

77
function(
88
Page, $,
9-
QueuesView, WorkersView, JobsView, ScheduledJobsView, IndexView, TaskPathsView, StatusView, TaskExceptionsView, IOView
9+
QueuesView, WorkersView, JobsView, ScheduledJobsView, IndexView, TaskPathsView, StatusView, TaskExceptionsView, IOView, WorkerGroupsView
1010
) {
1111

1212
return Page.extend({
@@ -116,6 +116,7 @@ define(["views/generic/page", "jquery",
116116
this.addChildPage('taskexceptions', new TaskExceptionsView());
117117
this.addChildPage('index', new IndexView());
118118
this.addChildPage('status', new StatusView());
119+
this.addChildPage('workergroups', new WorkerGroupsView());
119120

120121
return this;
121122
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
define(["jquery", "underscore", "models", "views/generic/page"],function($, _, Models, Page) {
2+
3+
return Page.extend({
4+
5+
el: '.js-page-workergroups',
6+
7+
template:"#tpl-page-workergroups",
8+
9+
events:{
10+
"click .submit": "submit"
11+
},
12+
13+
render: function() {
14+
var self = this;
15+
$.get("/api/workergroups").done(function(data) {
16+
self.renderTemplate();
17+
self.$("textarea").val(JSON.stringify(data["workergroups"], null, 8));
18+
});
19+
},
20+
21+
submit: function(el) {
22+
var self = this;
23+
24+
self.$("button")[0].innerHTML = "Wait...";
25+
26+
var val = self.$("textarea").val();
27+
28+
$.post("/api/workergroups", {"workergroups": val}).done(function(data) {
29+
if (data.status != "ok") {
30+
return alert("There was an error while saving!");
31+
}
32+
self.$("button")[0].innerHTML = "Save";
33+
});
34+
}
35+
});
36+
37+
});

mrq/dashboard/templates/index.html

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@
3838
<li class="js-nav-workers">
3939
<a href="/#workers">Workers</a>
4040
</li>
41+
<li class="js-nav-workergroups">
42+
<a href="/#workergroups">Worker groups</a>
43+
</li>
4144
<li class="js-nav-taskpaths">
4245
<a href="/#taskpaths">Paths</a>
4346
</li>
@@ -114,6 +117,7 @@
114117
<div class="js-page-taskpaths"></div>
115118
<div class="js-page-taskexceptions"></div>
116119
<div class="js-page-io"></div>
120+
<div class="js-page-workergroups"></div>
117121

118122

119123
</script>
@@ -246,6 +250,17 @@ <h3>Current I/O operations</h3>
246250
</div>
247251
</script>
248252

253+
<script id="tpl-page-workergroups" type="text/template">
254+
255+
<h3>Worker groups</h3>
256+
<div class="container">
257+
<div class="row">
258+
<textarea style="width:100%;height:400px;font-family:monospace;" onkeydown="if(event.keyCode===9){var v=this.value,s=this.selectionStart,e=this.selectionEnd;this.value=v.substring(0, s)+'\t'+v.substring(e);this.selectionStart=this.selectionEnd=s+1;return false;}"></textarea>
259+
<button class="submit">Save</button>
260+
</div>
261+
</div>
262+
</script>
263+
249264
<script id="tpl-page-index" type="text/template">
250265

251266
<h3>Overall</h3>

mrq/worker.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,12 @@ def ensure_indexes(self):
148148
[("datequeued", 1)], sparse=True, background=True)
149149

150150
self.mongodb_jobs.mrq_scheduled_jobs.ensure_index(
151-
[("hash", 1)], unique=True, background=False, drop_dups=True)
151+
[("hash", 1)], unique=True, background=False)
152+
153+
self.mongodb_jobs.mrq_agents.ensure_index(
154+
[("datereported", 1)], background=False, expireAfterSeconds=300)
155+
self.mongodb_jobs.mrq_agents.ensure_index(
156+
[("worker_group", 1)], background=False)
152157

153158
try:
154159
# This will be default in MongoDB 2.6

tests/test_agent.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -163,14 +163,22 @@ def test_agent_process(worker):
163163
time.sleep(3)
164164

165165
assert connections.mongodb_jobs.mrq_workers.count() == 1
166-
worker = connections.mongodb_jobs.mrq_workers.find_one()
167-
assert worker["status"] == "wait"
166+
w = connections.mongodb_jobs.mrq_workers.find_one()
167+
assert w["status"] == "wait"
168168

169169
connections.mongodb_jobs.mrq_workergroups.update_one({"_id": "xxx"}, {"$set": {"profiles": [
170170

171171
]}})
172172

173173
time.sleep(4)
174174

175-
worker = connections.mongodb_jobs.mrq_workers.find_one()
176-
assert worker["status"] == "stop"
175+
w = connections.mongodb_jobs.mrq_workers.find_one()
176+
assert w["status"] == "stop"
177+
178+
assert connections.mongodb_jobs.mrq_agents.count() == 1
179+
180+
worker.stop(deps=False)
181+
182+
assert connections.mongodb_jobs.mrq_agents.count() == 0
183+
184+
worker.stop_deps()

0 commit comments

Comments
 (0)