Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(91)

Side by Side Diff: chromium-jobqueue/app.py

Issue 23093011: Create tryserver appengine app. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/
Patch Set: Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
cmp 2013/08/22 04:44:12 2013? There should be a LICENSE file in the CL, t
agable 2013/08/22 13:43:42 Done, copied from depot_tools. Out of curiosity, w
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
4
5 import datetime
6 import json
7
8 import webapp2
9 from google.appengine.ext import ndb
10
11
12 DEFAULT_NAMESPACE = 'default'
13 DEFAULT_JOBS_TO_SERVE = 20
14
15
16 class Job(ndb.Model):
17 """Represents a single tryjob description.
18
19 Attributes:
20 description: A JSON blob representing the job itself.
21 created: A timestamp for when this job was posted.
22 last_served: A timestamp for the last time this job was served to a polling
23 tryserver. Default is epoch 0, so new jobs are "old".
cmp 2013/08/22 04:44:12 tryserver -> other name
agable 2013/08/22 13:43:42 Done.
24 taken: A boolean signalling that this job has been successfully picked up by
25 a trysever and can be dropped.
cmp 2013/08/22 04:44:12 tryserver -> other name
agable 2013/08/22 13:43:42 Done.
26 """
27 description = ndb.JsonProperty()
28 last_served = ndb.DateTimeProperty(
29 default=datetime.datetime.utcfromtimestamp(0))
30 taken = ndb.BooleanProperty(default=False)
31
32
33 class MainHandler(webapp2.RequestHandler):
34
35 def get(self):
36 self.response.write("""
37 <html>
38 <body>
39 <form action="/default/push" method="post">
40 <div><textarea name="job" rows="3" cols="60"></textarea></div>
41 <div><input type="submit" value="Add Job"></div>
42 </form>
43 <form action="/default/accept" method="post">
44 <div><textarea name="job" rows="1" cols="60"></textarea></div>
45 <div><input type="submit" value="Accept Job"></div>
46 </form>
47 </body>
48 </html>
49 """)
50
51
52 class PushHandler(webapp2.RequestHandler):
53
54 def post(self, project):
55 job = Job(description=self.request.get('job'), namespace=project)
56 job.put()
57
58
59 class PullHandler(webapp2.RequestHandler):
60
61 def post(self, project):
62 # Get the jobs we'd like to serve.
63 time_threshold = datetime.datetime.utcnow() - datetime.timedelta(seconds=30)
64 query = Job.query(namespace=project)
65 query = query.filter(Job.last_served < time_threshold)
66 query = query.filter(Job.taken == False)
67 query = query.order(Job.last_served)
68 jobs = query.fetch(DEFAULT_JOBS_TO_SERVE)
69
70 # Mark them as served.
71 for job in jobs:
72 job.last_served = datetime.datetime.utcnow()
73 job.put()
74
75 # Serve them.
76 result = []
77 for job in jobs:
78 job_blob = json.loads(job.description)
79 job_blob.update({'job_key': job.key.urlsafe()})
80 result.append(job_blob)
81 self.response.headers['Content-Type'] = 'application/json'
82 self.response.write(json.dumps(result))
83
84
85 class PeekHandler(webapp2.RequestHandler):
86
87 def get(self, project, job):
88 # Get the jobs we'd like to serve.
89 if job:
90 job_key = ndb.Key(urlsafe=job, namespace=project)
91 job = job_key.get()
92 jobs = [job]
93 else:
94 time_threshold = datetime.datetime.utcnow() - datetime.timedelta(seconds=3 0)
cmp 2013/08/22 04:44:12 wrap at 80 chars
agable 2013/08/22 13:43:42 Done.
95 query = Job.query(namespace=project)
96 query = query.filter(Job.last_served < time_threshold)
97 query = query.filter(Job.taken == False)
98 query = query.order(Job.last_served)
99 jobs = query.fetch(DEFAULT_JOBS_TO_SERVE)
100
101 # Serve them.
102 result = []
103 for job in jobs:
104 job_blob = json.loads(job.description)
105 job_blob.update({'job_key': job.key.urlsafe()})
106 result.append(job_blob)
107 self.response.headers['Content-Type'] = 'application/json'
108 self.response.write(json.dumps(result))
109
110
111 class AcceptHandler(webapp2.RequestHandler):
112
113 def post(self, project, job):
114 job_key = ndb.Key(urlsafe=job, namespace=project)
115 job = job_key.get()
116 if job.taken:
117 # This job has been previously accepted by someone else.
118 self.response.set_status(409)
119 job.taken = True
cmp 2013/08/22 04:44:12 I think this would be a perfect place to use pull
agable 2013/08/22 13:43:42 Agreed. Right now, the Pull/Accept paradigm is jus
120 job.put()
121
122
123 app = webapp2.WSGIApplication([
124 ('/', MainHandler),
125 ('/(.*)/push', PushHandler),
126 ('/(.*)/pull', PullHandler),
127 ('/(.*)/peek/?(.*)', PeekHandler),
128 ('/(.*)/accept/(.*)', AcceptHandler),
129 ])
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698