OLD | NEW |
1 # Copyright 2013 The Chromium Authors. All rights reserved. | 1 # Copyright 2013 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 logging | 5 import logging |
6 import time | 6 import time |
7 import traceback | 7 import traceback |
8 | 8 |
9 from app_yaml_helper import AppYamlHelper | 9 from app_yaml_helper import AppYamlHelper |
10 from appengine_wrappers import ( | 10 from appengine_wrappers import ( |
11 GetAppVersion, IsDeadlineExceededError, logservice) | 11 GetAppVersion, IsDeadlineExceededError, logservice) |
12 from branch_utility import BranchUtility | 12 from branch_utility import BranchUtility |
13 from compiled_file_system import CompiledFileSystem | 13 from compiled_file_system import CompiledFileSystem |
14 from data_source_registry import CreateDataSources | 14 from data_source_registry import CreateDataSources |
15 from empty_dir_file_system import EmptyDirFileSystem | 15 from empty_dir_file_system import EmptyDirFileSystem |
16 from environment import IsDevServer | 16 from environment import IsDevServer |
17 from file_system_util import CreateURLsFromPaths | 17 from file_system_util import CreateURLsFromPaths |
| 18 from future import Gettable, Future |
18 from github_file_system_provider import GithubFileSystemProvider | 19 from github_file_system_provider import GithubFileSystemProvider |
19 from host_file_system_provider import HostFileSystemProvider | 20 from host_file_system_provider import HostFileSystemProvider |
20 from object_store_creator import ObjectStoreCreator | 21 from object_store_creator import ObjectStoreCreator |
21 from render_servlet import RenderServlet | 22 from render_servlet import RenderServlet |
22 from server_instance import ServerInstance | 23 from server_instance import ServerInstance |
23 from servlet import Servlet, Request, Response | 24 from servlet import Servlet, Request, Response |
24 import svn_constants | 25 import svn_constants |
25 | 26 |
26 class _SingletonRenderServletDelegate(RenderServlet.Delegate): | 27 class _SingletonRenderServletDelegate(RenderServlet.Delegate): |
27 def __init__(self, server_instance): | 28 def __init__(self, server_instance): |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
144 def request_files_in_dir(path, prefix=''): | 145 def request_files_in_dir(path, prefix=''): |
145 '''Requests every file found under |path| in this host file system, with | 146 '''Requests every file found under |path| in this host file system, with |
146 a request prefix of |prefix|. | 147 a request prefix of |prefix|. |
147 ''' | 148 ''' |
148 files = [name for name, _ in CreateURLsFromPaths(trunk_fs, path, prefix)] | 149 files = [name for name, _ in CreateURLsFromPaths(trunk_fs, path, prefix)] |
149 return _RequestEachItem(path, files, render) | 150 return _RequestEachItem(path, files, render) |
150 | 151 |
151 results = [] | 152 results = [] |
152 | 153 |
153 try: | 154 try: |
| 155 # Start running the hand-written Cron methods first; they can be run in |
| 156 # parallel. They are resolved at the end. |
| 157 def run_cron_for_future(target): |
| 158 title = target.__class__.__name__ |
| 159 start_time = time.time() |
| 160 future = target.Cron() |
| 161 init_time = time.time() - start_time |
| 162 assert isinstance(future, Future), ( |
| 163 '%s.Cron() did not return a Future' % title) |
| 164 def resolve(): |
| 165 start_time = time.time() |
| 166 try: |
| 167 future.Get() |
| 168 except Exception as e: |
| 169 _cronlog.error('%s: error %s' % (title, traceback.format_exc())) |
| 170 results.append(False) |
| 171 if IsDeadlineExceededError(e): raise |
| 172 finally: |
| 173 resolve_time = time.time() - start_time |
| 174 _cronlog.info( |
| 175 '%s: used %s seconds, %s to initialize and %s to resolve' % |
| 176 (title, init_time + resolve_time, init_time, resolve_time)) |
| 177 return Future(delegate=Gettable(resolve)) |
| 178 |
| 179 targets = (CreateDataSources(server_instance).values() + |
| 180 [server_instance.content_providers]) |
| 181 title = 'initializing %s parallel Cron targets' % len(targets) |
| 182 start_time = time.time() |
| 183 _cronlog.info(title) |
| 184 try: |
| 185 cron_futures = [run_cron_for_future(target) for target in targets] |
| 186 finally: |
| 187 _cronlog.info('%s took %s seconds' % (title, time.time() - start_time)) |
| 188 |
| 189 |
154 # Rendering the public templates will also pull in all of the private | 190 # Rendering the public templates will also pull in all of the private |
155 # templates. | 191 # templates. |
156 results.append(request_files_in_dir(svn_constants.PUBLIC_TEMPLATE_PATH)) | 192 results.append(request_files_in_dir(svn_constants.PUBLIC_TEMPLATE_PATH)) |
157 | 193 |
158 # Rendering the public templates will have pulled in the .js and | 194 # Rendering the public templates will have pulled in the .js and |
159 # manifest.json files (for listing examples on the API reference pages), | 195 # manifest.json files (for listing examples on the API reference pages), |
160 # but there are still images, CSS, etc. | 196 # but there are still images, CSS, etc. |
161 results.append(request_files_in_dir(svn_constants.STATIC_PATH, | 197 results.append(request_files_in_dir(svn_constants.STATIC_PATH, |
162 prefix='static/')) | 198 prefix='static/')) |
163 | 199 |
164 # Samples are too expensive to run on the dev server, where there is no | 200 # Samples are too expensive to run on the dev server, where there is no |
165 # parallel fetch. | 201 # parallel fetch. |
166 if not IsDevServer(): | 202 if not IsDevServer(): |
167 # Fetch each individual sample file. | 203 # Fetch each individual sample file. |
168 results.append(request_files_in_dir(svn_constants.EXAMPLES_PATH, | 204 results.append(request_files_in_dir(svn_constants.EXAMPLES_PATH, |
169 prefix='extensions/examples/')) | 205 prefix='extensions/examples/')) |
170 | 206 |
171 # Fetch the zip file of each example (contains all the individual | 207 # Fetch the zip file of each example (contains all the individual |
172 # files). | 208 # files). |
173 example_zips = [] | 209 example_zips = [] |
174 for root, _, files in trunk_fs.Walk(svn_constants.EXAMPLES_PATH): | 210 for root, _, files in trunk_fs.Walk(svn_constants.EXAMPLES_PATH): |
175 example_zips.extend( | 211 example_zips.extend( |
176 root + '.zip' for name in files if name == 'manifest.json') | 212 root + '.zip' for name in files if name == 'manifest.json') |
177 results.append(_RequestEachItem( | 213 results.append(_RequestEachItem( |
178 'example zips', | 214 'example zips', |
179 example_zips, | 215 example_zips, |
180 lambda path: render('extensions/examples/' + path))) | 216 lambda path: render('extensions/examples/' + path))) |
181 | 217 |
182 def run_cron(data_source): | 218 # Resolve the hand-written Cron method futures. |
183 title = data_source.__class__.__name__ | 219 title = 'resolving %s parallel Cron targets' % len(targets) |
184 _cronlog.info('%s: starting' % title) | 220 _cronlog.info(title) |
185 start_time = time.time() | 221 start_time = time.time() |
186 try: | 222 try: |
187 data_source.Cron() | 223 for future in cron_futures: |
188 except Exception as e: | 224 future.Get() |
189 _cronlog.error('%s: error %s' % (title, traceback.format_exc())) | 225 finally: |
190 results.append(False) | 226 _cronlog.info('%s took %s seconds' % (title, time.time() - start_time)) |
191 if IsDeadlineExceededError(e): raise | |
192 finally: | |
193 _cronlog.info( | |
194 '%s: took %s seconds' % (title, time.time() - start_time)) | |
195 | |
196 for data_source in CreateDataSources(server_instance).values(): | |
197 run_cron(data_source) | |
198 | |
199 run_cron(server_instance.content_providers) | |
200 | 227 |
201 except: | 228 except: |
202 results.append(False) | 229 results.append(False) |
203 # This should never actually happen (each cron step does its own | 230 # This should never actually happen (each cron step does its own |
204 # conservative error checking), so re-raise no matter what it is. | 231 # conservative error checking), so re-raise no matter what it is. |
205 _cronlog.error('uncaught error: %s' % traceback.format_exc()) | 232 _cronlog.error('uncaught error: %s' % traceback.format_exc()) |
206 raise | 233 raise |
207 finally: | 234 finally: |
208 success = all(results) | 235 success = all(results) |
209 _cronlog.info('finished (%s)', 'success' if success else 'FAILED') | 236 _cronlog.info('finished (%s)', 'success' if success else 'FAILED') |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
261 branch_utility = self._delegate.CreateBranchUtility(object_store_creator) | 288 branch_utility = self._delegate.CreateBranchUtility(object_store_creator) |
262 host_file_system_provider = self._delegate.CreateHostFileSystemProvider( | 289 host_file_system_provider = self._delegate.CreateHostFileSystemProvider( |
263 object_store_creator, max_trunk_revision=revision) | 290 object_store_creator, max_trunk_revision=revision) |
264 github_file_system_provider = self._delegate.CreateGithubFileSystemProvider( | 291 github_file_system_provider = self._delegate.CreateGithubFileSystemProvider( |
265 object_store_creator) | 292 object_store_creator) |
266 return ServerInstance(object_store_creator, | 293 return ServerInstance(object_store_creator, |
267 CompiledFileSystem.Factory(object_store_creator), | 294 CompiledFileSystem.Factory(object_store_creator), |
268 branch_utility, | 295 branch_utility, |
269 host_file_system_provider, | 296 host_file_system_provider, |
270 github_file_system_provider) | 297 github_file_system_provider) |
OLD | NEW |