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

Side by Side Diff: scripts/master/try_job_rietveld.py

Issue 330283006: New RietveldPollerWithCache is working stable. Removed old RietveldPoller and the flag to choose be… (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/build
Patch Set: Created 6 years, 6 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
« no previous file with comments | « masters/master.tryserver.webrtc/master.cfg ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 import datetime 5 import datetime
6 import hashlib 6 import hashlib
7 import json 7 import json
8 import os 8 import os
9 import pytz 9 import pytz
10 import time 10 import time
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
97 postdata=urllib.urlencode(params)) 97 postdata=urllib.urlencode(params))
98 98
99 def _MakeSet(self, data): 99 def _MakeSet(self, data):
100 """Converts the input data string into a set of email addresses. 100 """Converts the input data string into a set of email addresses.
101 """ 101 """
102 emails = (email.strip() for email in data.splitlines()) 102 emails = (email.strip() for email in data.splitlines())
103 self._users = frozenset(email for email in emails if email) 103 self._users = frozenset(email for email in emails if email)
104 log.msg('Found %d users' % len(self._users)) 104 log.msg('Found %d users' % len(self._users))
105 105
106 106
107 class _RietveldPoller(base.PollingChangeSource):
108 """Polls Rietveld for any pending patch sets to build.
109
110 Periodically polls Rietveld to see if any patch sets have been marked by
111 users to be tried. If so, send them to the trybots.
112 """
113
114 def __init__(self, get_pending_endpoint, interval, cachepath=None):
115 """
116 Args:
117 get_pending_endpoint: Rietveld URL string used to retrieve jobs to try.
118 interval: Interval used to poll Rietveld, in seconds.
119 cachepath: Path to file where state to persist between master restarts
120 will be stored.
121 """
122 # Set interval time in base class.
123 self.pollInterval = interval
124
125 # A string URL for the Rietveld endpoint to query for pending try jobs.
126 self._get_pending_endpoint = get_pending_endpoint
127
128 # Cursor used to keep track of next patchset(s) to try. If the cursor
129 # is None, then try from the beginning.
130 self._cursor = None
131
132 # Try job parent of this poller.
133 self._try_job_rietveld = None
134
135 self._cachepath = cachepath
136
137 if self._cachepath:
138 if os.path.exists(self._cachepath):
139 with open(self._cachepath) as f:
140 # Using JSON allows us to be flexible and extend the format
141 # in a compatible way.
142 data = json.load(f)
143 self._cursor = data.get('cursor').encode('utf-8')
144
145 # base.PollingChangeSource overrides:
146 def poll(self):
147 """Polls Rietveld for any pending try jobs and submit them.
148
149 Returns:
150 A deferred objects to be called once the operation completes.
151 """
152 log.msg('RietveldPoller.poll')
153 d = defer.succeed(None)
154 d.addCallback(self._OpenUrl)
155 d.addCallback(self._ParseJson)
156 d.addErrback(log.err, 'error in RietveldPoller') # eat errors
157 return d
158
159 def setServiceParent(self, parent):
160 base.PollingChangeSource.setServiceParent(self, parent)
161 self._try_job_rietveld = parent
162
163 def _OpenUrl(self, _):
164 """Downloads pending patch sets from Rietveld.
165
166 Returns: A string containing the pending patchsets from Rietveld
167 encoded as JSON.
168 """
169 endpoint = self._get_pending_endpoint
170 if self._cursor:
171 sep = '&' if '?' in endpoint else '?'
172 endpoint = endpoint + '%scursor=%s' % (sep, self._cursor)
173
174 log.msg('RietveldPoller._OpenUrl: %s' % endpoint)
175 return client.getPage(endpoint, agent='buildbot', timeout=2*60)
176
177 def _ParseJson(self, json_string):
178 """Parses the JSON pending patch set information.
179
180 Args:
181 json_string: A string containing the serialized JSON jobs.
182
183 Returns: A list of pending try jobs. This is the list of all jobs returned
184 by Rietveld, not simply the ones we tried this time.
185 """
186 data = json.loads(json_string)
187 d = self._try_job_rietveld.SubmitJobs(data['jobs'])
188 def success_callback(value):
189 self._cursor = str(data['cursor'])
190 self._try_job_rietveld.processed_keys.clear()
191
192 if self._cachepath:
193 with open(self._cachepath, 'w') as f:
194 json.dump({'cursor': self._cursor}, f)
195
196 return value
197 d.addCallback(success_callback)
198 return d
199
200
201 class _RietveldPollerWithCache(base.PollingChangeSource): 107 class _RietveldPollerWithCache(base.PollingChangeSource):
202 """Polls Rietveld for any pending patch sets to build. 108 """Polls Rietveld for any pending patch sets to build.
203 109
204 Periodically polls Rietveld to see if any patch sets have been marked by 110 Periodically polls Rietveld to see if any patch sets have been marked by
205 users to be tried. If so, send them to the trybots. Uses cursor to download 111 users to be tried. If so, send them to the trybots. Uses cursor to download
206 all pages within a single poll. To avoid sending same jobs, keeps a cache of 112 all pages within a single poll. To avoid sending same jobs, keeps a cache of
207 the jobs that were already processed thus reducing chances of a duplicate job 113 the jobs that were already processed thus reducing chances of a duplicate job
208 submission and increasing robustness to bugs in Rietveld. On the first poll 114 submission and increasing robustness to bugs in Rietveld. On the first poll
209 this cache is initialized with jobs currently pending on the Buildbot. 115 this cache is initialized with jobs currently pending on the Buildbot.
210 """ 116 """
211 117
212 def __init__(self, pending_jobs_url, interval, cachepath=None): 118 def __init__(self, pending_jobs_url, interval):
213 """ 119 """
214 Args: 120 Args:
215 pending_jobs_url: Rietveld URL string used to retrieve jobs to try. 121 pending_jobs_url: Rietveld URL string used to retrieve jobs to try.
216 interval: Interval used to poll Rietveld, in seconds. 122 interval: Interval used to poll Rietveld, in seconds.
217 """ 123 """
218 self.pollInterval = interval 124 self.pollInterval = interval
219 self._try_job_rietveld = None 125 self._try_job_rietveld = None
220 self._pending_jobs_url = pending_jobs_url 126 self._pending_jobs_url = pending_jobs_url
221 self._cachepath = cachepath
222 self._processed_keys = None 127 self._processed_keys = None
223 128
224 # base.PollingChangeSource overrides: 129 # base.PollingChangeSource overrides:
225 def poll(self): 130 def poll(self):
226 """Polls Rietveld for any pending try jobs and submit them. 131 """Polls Rietveld for any pending try jobs and submit them.
227 132
228 Returns: 133 Returns:
229 A deferred object to be called once the operation completes. 134 A deferred object to be called once the operation completes.
230 """ 135 """
231 136
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
343 else: 248 else:
344 num_removed += 1 249 num_removed += 1
345 log.msg('[RPWC] Removed %d old jobs from the cache.' % num_removed) 250 log.msg('[RPWC] Removed %d old jobs from the cache.' % num_removed)
346 self._processed_keys = new_processed_keys 251 self._processed_keys = new_processed_keys
347 252
348 253
349 class TryJobRietveld(TryJobBase): 254 class TryJobRietveld(TryJobBase):
350 """A try job source that gets jobs from pending Rietveld patch sets.""" 255 """A try job source that gets jobs from pending Rietveld patch sets."""
351 256
352 def __init__(self, name, pools, properties=None, last_good_urls=None, 257 def __init__(self, name, pools, properties=None, last_good_urls=None,
353 code_review_sites=None, project=None, filter_master=False, 258 code_review_sites=None, project=None, filter_master=False):
354 cachepath=None, cache_processed_jobs=False):
355 """Creates a try job source for Rietveld patch sets. 259 """Creates a try job source for Rietveld patch sets.
356 260
357 Args: 261 Args:
358 name: Name of this scheduler. 262 name: Name of this scheduler.
359 pools: No idea. 263 pools: No idea.
360 properties: Extra build properties specific to this scheduler. 264 properties: Extra build properties specific to this scheduler.
361 last_good_urls: Dictionary of project to last known good build URL. 265 last_good_urls: Dictionary of project to last known good build URL.
362 code_review_sites: Dictionary of project to code review site. This 266 code_review_sites: Dictionary of project to code review site. This
363 class care only about the 'chrome' project. 267 class care only about the 'chrome' project.
364 project: The name of the project whose review site URL to extract. 268 project: The name of the project whose review site URL to extract.
365 If the project is not found in the dictionary, an exception is 269 If the project is not found in the dictionary, an exception is
366 raised. 270 raised.
367 filter_master: Filter try jobs by master name. Necessary if several try 271 filter_master: Filter try jobs by master name. Necessary if several try
368 masters share the same rietveld instance. 272 masters share the same rietveld instance.
369 """ 273 """
370 TryJobBase.__init__(self, name, pools, properties, 274 TryJobBase.__init__(self, name, pools, properties,
371 last_good_urls, code_review_sites) 275 last_good_urls, code_review_sites)
372 endpoint = self._GetRietveldEndPointForProject( 276 endpoint = self._GetRietveldEndPointForProject(
373 code_review_sites, project, filter_master) 277 code_review_sites, project, filter_master)
374 278
375 if cache_processed_jobs: 279 self._poller = _RietveldPollerWithCache(endpoint, interval=10)
376 self._poller = _RietveldPollerWithCache(endpoint, interval=10)
377 else:
378 self._poller = _RietveldPoller(endpoint, interval=10, cachepath=cachepath)
379 self._valid_users = _ValidUserPoller(interval=12 * 60 * 60) 280 self._valid_users = _ValidUserPoller(interval=12 * 60 * 60)
380 self._project = project 281 self._project = project
381 282
382 # Cleared by _RietveldPoller._ParseJson's success callback. 283 # Cleared by _RietveldPoller._ParseJson's success callback.
383 self.processed_keys = set() 284 self.processed_keys = set()
384 285
385 log.msg('TryJobRietveld created, get_pending_endpoint=%s ' 286 log.msg('TryJobRietveld created, get_pending_endpoint=%s '
386 'project=%s' % (endpoint, project)) 287 'project=%s' % (endpoint, project))
387 288
388 @staticmethod 289 @staticmethod
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
499 else: 400 else:
500 self.processed_keys.add(job['key']) 401 self.processed_keys.add(job['key'])
501 log.err('Rietveld not updated: no corresponding service found.') 402 log.err('Rietveld not updated: no corresponding service found.')
502 403
503 # TryJobBase overrides: 404 # TryJobBase overrides:
504 def setServiceParent(self, parent): 405 def setServiceParent(self, parent):
505 TryJobBase.setServiceParent(self, parent) 406 TryJobBase.setServiceParent(self, parent)
506 self._poller.setServiceParent(self) 407 self._poller.setServiceParent(self)
507 self._poller.master = self.master 408 self._poller.master = self.master
508 self._valid_users.setServiceParent(self) 409 self._valid_users.setServiceParent(self)
OLDNEW
« no previous file with comments | « masters/master.tryserver.webrtc/master.cfg ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698