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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: chromium-jobqueue/app.py
===================================================================
--- chromium-jobqueue/app.py (revision 0)
+++ chromium-jobqueue/app.py (revision 0)
@@ -0,0 +1,129 @@
+# 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
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import datetime
+import json
+
+import webapp2
+from google.appengine.ext import ndb
+
+
+DEFAULT_NAMESPACE = 'default'
+DEFAULT_JOBS_TO_SERVE = 20
+
+
+class Job(ndb.Model):
+ """Represents a single tryjob description.
+
+ Attributes:
+ description: A JSON blob representing the job itself.
+ created: A timestamp for when this job was posted.
+ last_served: A timestamp for the last time this job was served to a polling
+ 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.
+ taken: A boolean signalling that this job has been successfully picked up by
+ a trysever and can be dropped.
cmp 2013/08/22 04:44:12 tryserver -> other name
agable 2013/08/22 13:43:42 Done.
+ """
+ description = ndb.JsonProperty()
+ last_served = ndb.DateTimeProperty(
+ default=datetime.datetime.utcfromtimestamp(0))
+ taken = ndb.BooleanProperty(default=False)
+
+
+class MainHandler(webapp2.RequestHandler):
+
+ def get(self):
+ self.response.write("""
+<html>
+ <body>
+ <form action="/default/push" method="post">
+ <div><textarea name="job" rows="3" cols="60"></textarea></div>
+ <div><input type="submit" value="Add Job"></div>
+ </form>
+ <form action="/default/accept" method="post">
+ <div><textarea name="job" rows="1" cols="60"></textarea></div>
+ <div><input type="submit" value="Accept Job"></div>
+ </form>
+ </body>
+</html>
+""")
+
+
+class PushHandler(webapp2.RequestHandler):
+
+ def post(self, project):
+ job = Job(description=self.request.get('job'), namespace=project)
+ job.put()
+
+
+class PullHandler(webapp2.RequestHandler):
+
+ def post(self, project):
+ # Get the jobs we'd like to serve.
+ time_threshold = datetime.datetime.utcnow() - datetime.timedelta(seconds=30)
+ query = Job.query(namespace=project)
+ query = query.filter(Job.last_served < time_threshold)
+ query = query.filter(Job.taken == False)
+ query = query.order(Job.last_served)
+ jobs = query.fetch(DEFAULT_JOBS_TO_SERVE)
+
+ # Mark them as served.
+ for job in jobs:
+ job.last_served = datetime.datetime.utcnow()
+ job.put()
+
+ # Serve them.
+ result = []
+ for job in jobs:
+ job_blob = json.loads(job.description)
+ job_blob.update({'job_key': job.key.urlsafe()})
+ result.append(job_blob)
+ self.response.headers['Content-Type'] = 'application/json'
+ self.response.write(json.dumps(result))
+
+
+class PeekHandler(webapp2.RequestHandler):
+
+ def get(self, project, job):
+ # Get the jobs we'd like to serve.
+ if job:
+ job_key = ndb.Key(urlsafe=job, namespace=project)
+ job = job_key.get()
+ jobs = [job]
+ else:
+ time_threshold = datetime.datetime.utcnow() - datetime.timedelta(seconds=30)
cmp 2013/08/22 04:44:12 wrap at 80 chars
agable 2013/08/22 13:43:42 Done.
+ query = Job.query(namespace=project)
+ query = query.filter(Job.last_served < time_threshold)
+ query = query.filter(Job.taken == False)
+ query = query.order(Job.last_served)
+ jobs = query.fetch(DEFAULT_JOBS_TO_SERVE)
+
+ # Serve them.
+ result = []
+ for job in jobs:
+ job_blob = json.loads(job.description)
+ job_blob.update({'job_key': job.key.urlsafe()})
+ result.append(job_blob)
+ self.response.headers['Content-Type'] = 'application/json'
+ self.response.write(json.dumps(result))
+
+
+class AcceptHandler(webapp2.RequestHandler):
+
+ def post(self, project, job):
+ job_key = ndb.Key(urlsafe=job, namespace=project)
+ job = job_key.get()
+ if job.taken:
+ # This job has been previously accepted by someone else.
+ self.response.set_status(409)
+ 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
+ job.put()
+
+
+app = webapp2.WSGIApplication([
+ ('/', MainHandler),
+ ('/(.*)/push', PushHandler),
+ ('/(.*)/pull', PullHandler),
+ ('/(.*)/peek/?(.*)', PeekHandler),
+ ('/(.*)/accept/(.*)', AcceptHandler),
+])

Powered by Google App Engine
This is Rietveld 408576698