Skip to content

Commit 23e766a

Browse files
author
Matt George
committed
changed the views from jinja2 to pystache
also slid in a fix to the workers module that was found while updating the resweb package.
1 parent 3490d1a commit 23e766a

32 files changed

+628
-227
lines changed

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ simplejson==2.0.9
22
Jinja2==2.2.1
33
itty==0.6.1
44
redis==0.6.0
5+
pystache==0.1.0

src/pyres/worker.py

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ def __init__(self, queues=[], server="localhost:6379"):
1212
self.validate_queues()
1313
self._shutdown = False
1414
self.child = None
15+
self.pid = os.getpid()
1516
if isinstance(server,basestring):
1617
self.resq = ResQ(server)
1718
elif isinstance(server, ResQ):
@@ -55,18 +56,33 @@ def kill_child(self, signum, frame):
5556
print "Killing child at %s" % self.child
5657
os.kill(self.child, signal.SIGKILL)
5758

59+
def __str__(self):
60+
if getattr(self,'id', None):
61+
return self.id
62+
hostname = os.uname()[1]
63+
#pid = os.getpid()
64+
return '%s:%s:%s' % (hostname, self.pid, ','.join(self.queues))
65+
5866
def work(self, interval=5):
5967
self.startup()
6068
while True:
6169
if self._shutdown:
70+
print 'shutdown scheduled'
6271
break
6372
job = self.reserve()
6473
if job:
6574
print "got: %s" % job
6675
self.child = os.fork()
6776
if self.child:
6877
print 'Forked %s at %s' % (self.child, datetime.datetime.now())
69-
os.waitpid(self.child, 0)
78+
try:
79+
os.waitpid(self.child, 0)
80+
except OSError, ose:
81+
import errno
82+
if ose.errno != errno.EINTR:
83+
raise ose
84+
#os.wait()
85+
print 'Done waiting'
7086
else:
7187
print 'Processing %s since %s' % (job._queue, datetime.datetime.now())
7288
self.process(job)
@@ -102,15 +118,19 @@ def reserve(self):
102118
return job
103119

104120
def working_on(self, job):
121+
print 'marking as working on'
105122
data = {
106123
'queue': job._queue,
107124
'run_at': str(datetime.datetime.now()),
108125
'payload': job._payload
109126
}
110127
data = simplejson.dumps(data)
111128
self.resq.redis["worker:%s" % str(self)] = data
129+
print "worker:%s" % str(self)
130+
print self.resq.redis["worker:%s" % str(self)]
112131

113132
def done_working(self):
133+
print 'done working'
114134
self.processed()
115135
self.resq.redis.delete("worker:%s" % str(self))
116136

@@ -132,17 +152,16 @@ def job(self):
132152
return ResQ.decode(data)
133153
return {}
134154

135-
def __str__(self):
136-
if getattr(self,'id', None):
137-
return self.id
138-
import os;
139-
hostname = os.uname()[1]
140-
pid = os.getpid()
141-
return '%s:%s:%s' % (hostname, pid, ','.join(self.queues))
155+
def processing(self):
156+
return self.job()
157+
158+
def state(self):
159+
return 'working' if self.resq.redis.exists('worker:%s' % self) else 'idle'
160+
142161

143162
@classmethod
144163
def run(cls, queues, server):
145-
worker = cls(queues=queues, host=server)
164+
worker = cls(queues=queues, server=server)
146165
worker.work()
147166

148167
@classmethod
@@ -151,7 +170,7 @@ def all(cls, host="localhost:6379"):
151170
resq = ResQ(host)
152171
elif isinstance(host, ResQ):
153172
resq = host
154-
return resq.redis.smembers('workers')
173+
return [Worker.find(w,resq) for w in resq.redis.smembers('workers')]
155174

156175
@classmethod
157176
def working(cls, host):
@@ -161,8 +180,7 @@ def working(cls, host):
161180
resq = host
162181
total = []
163182
for key in Worker.all(host):
164-
if Worker.exists(key, resq):
165-
total.append('worker:%s' % key)
183+
total.append('worker:%s' % key)
166184
names = []
167185
for key in total:
168186
value = resq.redis.get(key)
@@ -193,6 +211,7 @@ def exists(cls, worker_id, resq):
193211
parser.add_option("-s", dest="server", default="localhost:6379")
194212
(options,args) = parser.parse_args()
195213
if not options.queue_list:
214+
parser.print_help()
196215
parser.error("Please give each worker at least one queue.")
197216
queues = options.queue_list.split(',')
198217
import sys

src/resweb/media/idle.png

661 Bytes
Loading

src/resweb/media/jquery-1.3.2.min.js

Lines changed: 19 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
// All credit goes to Rick Olson.
2+
(function($) {
3+
$.fn.relatizeDate = function() {
4+
return $(this).each(function() {
5+
if ($(this).hasClass( 'relatized' )) return
6+
$(this).text( $.relatizeDate(this) ).addClass( 'relatized' )
7+
})
8+
}
9+
10+
$.relatizeDate = function(element) {
11+
return $.relatizeDate.timeAgoInWords( new Date($(element).text()) )
12+
}
13+
14+
// shortcut
15+
$r = $.relatizeDate
16+
17+
$.extend($.relatizeDate, {
18+
shortDays: [ 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat' ],
19+
days: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
20+
shortMonths: [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ],
21+
months: [ 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December' ],
22+
23+
/**
24+
* Given a formatted string, replace the necessary items and return.
25+
* Example: Time.now().strftime("%B %d, %Y") => February 11, 2008
26+
* @param {String} format The formatted string used to format the results
27+
*/
28+
strftime: function(date, format) {
29+
var day = date.getDay(), month = date.getMonth();
30+
var hours = date.getHours(), minutes = date.getMinutes();
31+
32+
var pad = function(num) {
33+
var string = num.toString(10);
34+
return new Array((2 - string.length) + 1).join('0') + string
35+
};
36+
37+
return format.replace(/\%([aAbBcdHImMpSwyY])/g, function(part) {
38+
switch(part[1]) {
39+
case 'a': return $r.shortDays[day]; break;
40+
case 'A': return $r.days[day]; break;
41+
case 'b': return $r.shortMonths[month]; break;
42+
case 'B': return $r.months[month]; break;
43+
case 'c': return date.toString(); break;
44+
case 'd': return pad(date.getDate()); break;
45+
case 'H': return pad(hours); break;
46+
case 'I': return pad((hours + 12) % 12); break;
47+
case 'm': return pad(month + 1); break;
48+
case 'M': return pad(minutes); break;
49+
case 'p': return hours > 12 ? 'PM' : 'AM'; break;
50+
case 'S': return pad(date.getSeconds()); break;
51+
case 'w': return day; break;
52+
case 'y': return pad(date.getFullYear() % 100); break;
53+
case 'Y': return date.getFullYear().toString(); break;
54+
}
55+
})
56+
},
57+
58+
timeAgoInWords: function(targetDate, includeTime) {
59+
return $r.distanceOfTimeInWords(targetDate, new Date(), includeTime);
60+
},
61+
62+
/**
63+
* Return the distance of time in words between two Date's
64+
* Example: '5 days ago', 'about an hour ago'
65+
* @param {Date} fromTime The start date to use in the calculation
66+
* @param {Date} toTime The end date to use in the calculation
67+
* @param {Boolean} Include the time in the output
68+
*/
69+
distanceOfTimeInWords: function(fromTime, toTime, includeTime) {
70+
var delta = parseInt((toTime.getTime() - fromTime.getTime()) / 1000);
71+
if (delta < 60) {
72+
return 'just now';
73+
} else if (delta < 120) {
74+
return 'about a minute ago';
75+
} else if (delta < (45*60)) {
76+
return (parseInt(delta / 60)).toString() + ' minutes ago';
77+
} else if (delta < (120*60)) {
78+
return 'about an hour ago';
79+
} else if (delta < (24*60*60)) {
80+
return 'about ' + (parseInt(delta / 3600)).toString() + ' hours ago';
81+
} else if (delta < (48*60*60)) {
82+
return '1 day ago';
83+
} else {
84+
var days = (parseInt(delta / 86400)).toString();
85+
if (days > 5) {
86+
var fmt = '%B %d, %Y'
87+
if (includeTime) fmt += ' %I:%M %p'
88+
return $r.strftime(fromTime, fmt);
89+
} else {
90+
return days + " days ago"
91+
}
92+
}
93+
}
94+
})
95+
})(jQuery);

src/resweb/media/poll.png

627 Bytes
Loading

src/resweb/media/ranger.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
var poll_interval = 2;
2+
3+
$(function() {
4+
5+
$('.time').relatizeDate()
6+
$('.backtrace').click(function() {
7+
$(this).next().toggle()
8+
return false
9+
})
10+
11+
$('a[rel=poll]').click(function() {
12+
var href = $(this).attr('href')
13+
$(this).parent().text('Starting...')
14+
$("#main").addClass('polling')
15+
setInterval(function() {
16+
$.ajax({dataType:'text', type:'get', url:href, success:function(data) {
17+
$('#main').html(data)
18+
$('#main .time').relatizeDate()
19+
}})
20+
}, poll_interval * 1000)
21+
return false
22+
})
23+
24+
})

src/resweb/media/reset.css

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
html, body, div, span, applet, object, iframe,
2+
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
3+
a, abbr, acronym, address, big, cite, code,
4+
del, dfn, em, font, img, ins, kbd, q, s, samp,
5+
small, strike, strong, sub, sup, tt, var,
6+
dl, dt, dd, ul, li,
7+
form, label, legend,
8+
table, caption, tbody, tfoot, thead, tr, th, td {
9+
margin: 0;
10+
padding: 0;
11+
border: 0;
12+
outline: 0;
13+
font-weight: inherit;
14+
font-style: normal;
15+
font-size: 100%;
16+
font-family: inherit;
17+
}
18+
19+
:focus {
20+
outline: 0;
21+
}
22+
23+
body {
24+
line-height: 1;
25+
}
26+
27+
ul {
28+
list-style: none;
29+
}
30+
31+
table {
32+
border-collapse: collapse;
33+
border-spacing: 0;
34+
}
35+
36+
caption, th, td {
37+
text-align: left;
38+
font-weight: normal;
39+
}
40+
41+
blockquote:before, blockquote:after,
42+
q:before, q:after {
43+
content: "";
44+
}
45+
46+
blockquote, q {
47+
quotes: "" "";
48+
}

src/resweb/media/style.css

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
html { background:#efefef; font-family:Arial, Verdana, sans-serif; font-size:13px; }
2+
body { padding:0; margin:0; }
3+
4+
.header { background:#000; padding:8px 5% 0 5%; border-bottom:1px solid #444;border-bottom:5px solid #ce1212;}
5+
.header h1 { color:#333; font-size:90%; font-weight:bold; margin-bottom:6px;}
6+
.header ul li { display:inline;}
7+
.header ul li a { color:#fff; text-decoration:none; margin-right:10px; display:inline-block; padding:8px; -webkit-border-top-right-radius:6px; -webkit-border-top-left-radius:6px; }
8+
.header ul li a:hover { background:#333;}
9+
.header ul li.current a { background:#ce1212; font-weight:bold; color:#fff;}
10+
11+
.subnav { padding:2px 5% 7px 5%; background:#ce1212; font-size:90%;}
12+
.subnav li { display:inline;}
13+
.subnav li a { color:#fff; text-decoration:none; margin-right:10px; display:inline-block; background:#dd5b5b; padding:5px; -webkit-border-radius:3px; -moz-border-radius:3px;}
14+
.subnav li.current a { background:#fff; font-weight:bold; color:#ce1212;}
15+
.subnav li a:active { background:#b00909;}
16+
17+
#main { padding:10px 5%; background:#fff; overflow:hidden; }
18+
#main .logo { float:right; margin:10px;}
19+
#main span.hl { background:#efefef; padding:2px;}
20+
#main h1 { margin:10px 0; font-size:190%; font-weight:bold; color:#ce1212;}
21+
#main h2 { margin:10px 0; font-size:130%;}
22+
#main table { width:100%; margin:10px 0;}
23+
#main table tr td, #main table tr th { border:1px solid #ccc; padding:6px;}
24+
#main table tr th { background:#efefef; color:#888; font-size:80%; font-weight:bold;}
25+
#main table tr td.no-data { text-align:center; padding:40px 0; color:#999; font-style:italic; font-size:130%;}
26+
#main a { color:#111;}
27+
#main p { margin:5px 0;}
28+
#main p.intro { margin-bottom:15px; font-size:85%; color:#999; margin-top:0; line-height:1.3;}
29+
#main h1.wi { margin-bottom:5px;}
30+
#main p.sub { font-size:95%; color:#999;}
31+
32+
#main table.queues { width:40%;}
33+
#main table.queues td.queue { font-weight:bold; width:50%;}
34+
#main table.queues tr.failed td { background:#ffecec; border-top:2px solid #d37474; font-size:90%; color:#d37474;}
35+
#main table.queues tr.failed td a{ color:#d37474;}
36+
37+
#main table.jobs td.class { font-family:Monaco, "Courier New", monospace; font-size:90%; width:50%;}
38+
#main table.jobs td.args{ width:50%;}
39+
40+
#main table.workers td.icon {width:1%; background:#efefef;text-align:center;}
41+
#main table.workers td.where { width:25%;}
42+
#main table.workers td.queues { width:35%;}
43+
#main .queue-tag { background:#b1d2e9; padding:2px; margin:0 3px; font-size:80%; text-decoration:none; text-transform:uppercase; font-weight:bold; color:#3274a2; -webkit-border-radius:4px; -moz-border-radius:4px;}
44+
#main table.workers td.queues.queue { width:10%;}
45+
#main table.workers td.process { width:35%;}
46+
#main table.workers td.process span.waiting { color:#999; font-size:90%;}
47+
#main table.workers td.process small { font-size:80%; margin-left:5px;}
48+
#main table.workers td.process code { font-family:Monaco, "Courier New", monospace; font-size:90%;}
49+
#main table.workers td.process small a { color:#999;}
50+
#main.polling table.workers tr.working td { background:#f4ffe4; color:#7ac312;}
51+
#main.polling table.workers tr.working td.where a { color:#7ac312;}
52+
#main.polling table.workers tr.working td.process code { font-weight:bold;}
53+
54+
55+
#main table.stats th { font-size:100%; width:40%; color:#000;}
56+
#main hr { border:0; border-top:5px solid #efefef; margin:15px 0;}
57+
58+
#footer { padding:10px 5%; background:#efefef; color:#999; font-size:85%; line-height:1.5; border-top:5px solid #ccc; padding-top:10px;}
59+
#footer p a { color:#999;}
60+
61+
#main p.poll { background:url(poll.png) no-repeat 0 2px; padding:3px 0; padding-left:23px; float:right; font-size:85%; }
62+
63+
#main ul.failed {}
64+
#main ul.failed li {background:-webkit-gradient(linear, left top, left bottom, from(#efefef), to(#fff)) #efefef; margin-top:10px; padding:10px; overflow:hidden; -webkit-border-radius:5px; border:1px solid #ccc; }
65+
#main ul.failed li dl dt {font-size:80%; color:#999; width:60px; float:left; padding-top:1px; text-align:right;}
66+
#main ul.failed li dl dd {margin-bottom:10px; margin-left:70px;}
67+
#main ul.failed li dl dd code, #main ul.failed li dl dd pre { font-family:Monaco, "Courier New", monospace; font-size:90%;}
68+
#main ul.failed li dl dd.error a {font-family:Monaco, "Courier New", monospace; font-size:90%; }
69+
#main ul.failed li dl dd.error pre { margin-top:3px; line-height:1.3;}
70+
71+
#main p.pagination { background:#efefef; padding:10px; overflow:hidden;}
72+
#main p.pagination a.less { float:left;}
73+
#main p.pagination a.more { float:right;}
74+
75+
#main form.clear-failed {float:right; margin-top:-10px;}

src/resweb/media/working.png

792 Bytes
Loading

0 commit comments

Comments
 (0)