Chromium Code Reviews| 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, DeadlineExceededError, IsDevServer, logservice) | 11 GetAppVersion, IsDevServer, logservice) |
|
方觉(Fang Jue)
2013/08/14 01:47:42
DeadlineExceededError can still happen even if it'
| |
| 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 empty_dir_file_system import EmptyDirFileSystem | 14 from empty_dir_file_system import EmptyDirFileSystem |
| 15 from file_system_util import CreateURLsFromPaths | 15 from file_system_util import CreateURLsFromPaths |
| 16 from github_file_system import GithubFileSystem | 16 from github_file_system import GithubFileSystem |
| 17 from host_file_system_creator import HostFileSystemCreator | 17 from host_file_system_creator import HostFileSystemCreator |
| 18 from object_store_creator import ObjectStoreCreator | 18 from object_store_creator import ObjectStoreCreator |
| 19 from render_servlet import RenderServlet | 19 from render_servlet import RenderServlet |
| 20 from server_instance import ServerInstance | 20 from server_instance import ServerInstance |
| 21 from servlet import Servlet, Request, Response | 21 from servlet import Servlet, Request, Response |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 47 def CreateAppSamplesFileSystem(self, object_store_creator): | 47 def CreateAppSamplesFileSystem(self, object_store_creator): |
| 48 # TODO(kalman): CachingFileSystem wrapper for GithubFileSystem, but it's | 48 # TODO(kalman): CachingFileSystem wrapper for GithubFileSystem, but it's |
| 49 # not supported yet (see comment there). | 49 # not supported yet (see comment there). |
| 50 return (EmptyDirFileSystem() if IsDevServer() else | 50 return (EmptyDirFileSystem() if IsDevServer() else |
| 51 GithubFileSystem.Create(object_store_creator)) | 51 GithubFileSystem.Create(object_store_creator)) |
| 52 | 52 |
| 53 def GetAppVersion(self): | 53 def GetAppVersion(self): |
| 54 return GetAppVersion() | 54 return GetAppVersion() |
| 55 | 55 |
| 56 def Get(self): | 56 def Get(self): |
| 57 # Crons often time out, and when they do *and* then eventually try to | |
| 58 # flush logs they die. Turn off autoflush and manually do so at the end. | |
| 59 logservice.AUTOFLUSH_ENABLED = False | |
| 60 try: | |
| 61 return self._GetImpl() | |
| 62 finally: | |
| 63 logservice.flush() | |
| 64 | |
| 65 def _GetImpl(self): | |
| 66 # Cron strategy: | 57 # Cron strategy: |
| 67 # | 58 # |
| 68 # Find all public template files and static files, and render them. Most of | 59 # Find all public template files and static files, and render them. Most of |
| 69 # the time these won't have changed since the last cron run, so it's a | 60 # the time these won't have changed since the last cron run, so it's a |
| 70 # little wasteful, but hopefully rendering is really fast (if it isn't we | 61 # little wasteful, but hopefully rendering is really fast (if it isn't we |
| 71 # have a problem). | 62 # have a problem). |
| 72 logging.info('cron: starting') | 63 logging.info('cron: starting') |
| 73 | 64 |
| 74 # This is returned every time RenderServlet wants to create a new | 65 # This is returned every time RenderServlet wants to create a new |
| 75 # ServerInstance. | 66 # ServerInstance. |
| 76 server_instance = self._GetSafeServerInstance() | 67 server_instance = self._GetSafeServerInstance() |
| 77 | 68 |
| 78 def get_via_render_servlet(path): | 69 def get_via_render_servlet(path): |
| 79 request = Request(path, self._request.host, self._request.headers) | 70 request = Request(path, self._request.host, self._request.headers) |
| 80 delegate = _SingletonRenderServletDelegate(server_instance) | 71 delegate = _SingletonRenderServletDelegate(server_instance) |
| 81 return RenderServlet(request, delegate).Get() | 72 return RenderServlet(request, delegate).Get() |
| 82 | 73 |
| 83 def run_cron_for_dir(d, path_prefix=''): | 74 def run_cron_for_dir(d, path_prefix=''): |
| 84 success = True | 75 success = True |
| 85 start_time = time.time() | 76 start_time = time.time() |
| 86 files = dict( | 77 files = dict( |
| 87 CreateURLsFromPaths(server_instance.host_file_system, d, path_prefix)) | 78 CreateURLsFromPaths(server_instance.host_file_system, d, path_prefix)) |
| 88 logging.info('cron: rendering %s files from %s...' % (len(files), d)) | 79 logging.info('cron: rendering %s files from %s...' % (len(files), d)) |
| 89 try: | 80 try: |
| 90 for i, path in enumerate(files): | 81 for i, path in enumerate(files): |
| 91 error = None | 82 response = get_via_render_servlet(path) |
| 92 try: | 83 if response.status != 200: |
| 93 response = get_via_render_servlet(path) | 84 logging.error('cron: error rendering %s: %s' % ( |
| 94 if response.status != 200: | 85 path, 'Got %s response' % response.status)) |
| 95 error = 'Got %s response' % response.status | |
| 96 except DeadlineExceededError: | |
| 97 logging.error( | |
| 98 'cron: deadline exceeded rendering %s (%s of %s): %s' % ( | |
| 99 path, i + 1, len(files), traceback.format_exc())) | |
| 100 raise | |
| 101 except error: | |
| 102 pass | |
| 103 if error: | |
| 104 logging.error('cron: error rendering %s: %s' % (path, error)) | |
| 105 success = False | 86 success = False |
| 106 finally: | 87 finally: |
| 107 logging.info('cron: rendering %s files from %s took %s seconds' % ( | 88 logging.info('cron: rendering %s files from %s took %s seconds' % ( |
| 108 len(files), d, time.time() - start_time)) | 89 len(files), d, time.time() - start_time)) |
| 109 return success | 90 return success |
| 110 | 91 |
| 111 success = True | 92 success = True |
| 112 try: | |
| 113 # Render all of the publicly accessible files. | |
| 114 cron_runs = [ | |
| 115 # Note: rendering the public templates will pull in all of the private | |
| 116 # templates. | |
| 117 (svn_constants.PUBLIC_TEMPLATE_PATH, ''), | |
| 118 # Note: rendering the public templates will have pulled in the .js | |
| 119 # and manifest.json files (for listing examples on the API reference | |
| 120 # pages), but there are still images, CSS, etc. | |
| 121 (svn_constants.STATIC_PATH, 'static/'), | |
| 122 ] | |
| 123 if not IsDevServer(): | |
| 124 cron_runs.append( | |
| 125 (svn_constants.EXAMPLES_PATH, 'extensions/examples/')) | |
| 126 | 93 |
| 127 # Note: don't try to short circuit any of this stuff. We want to run | 94 # Render all of the publicly accessible files. |
| 128 # the cron for all the directories regardless of intermediate | 95 cron_runs = [ |
| 129 # failures. | 96 # Note: rendering the public templates will pull in all of the private |
| 130 for path, path_prefix in cron_runs: | 97 # templates. |
| 131 success = run_cron_for_dir(path, path_prefix=path_prefix) and success | 98 (svn_constants.PUBLIC_TEMPLATE_PATH, ''), |
| 99 # Note: rendering the public templates will have pulled in the .js | |
| 100 # and manifest.json files (for listing examples on the API reference | |
| 101 # pages), but there are still images, CSS, etc. | |
| 102 (svn_constants.STATIC_PATH, 'static/'), | |
| 103 ] | |
| 104 if not IsDevServer(): | |
| 105 cron_runs.append( | |
| 106 (svn_constants.EXAMPLES_PATH, 'extensions/examples/')) | |
| 132 | 107 |
| 133 # TODO(kalman): Generic way for classes to request cron access. The next | 108 # Note: don't try to short circuit any of this stuff. We want to run |
| 134 # two special cases are ugly. It would potentially greatly speed up cron | 109 # the cron for all the directories regardless of intermediate |
| 135 # runs, too. | 110 # failures. |
| 111 for path, path_prefix in cron_runs: | |
| 112 success = run_cron_for_dir(path, path_prefix=path_prefix) and success | |
| 136 | 113 |
| 137 # Extension examples have zip files too. Well, so do apps, but the app | 114 # TODO(kalman): Generic way for classes to request cron access. The next |
| 138 # file system doesn't get the Offline treatment so they don't need cron. | 115 # two special cases are ugly. It would potentially greatly speed up cron |
| 139 if not IsDevServer(): | 116 # runs, too. |
| 140 manifest_json = 'manifest.json' | |
| 141 example_zips = [] | |
| 142 for root, _, files in server_instance.host_file_system.Walk( | |
| 143 svn_constants.EXAMPLES_PATH): | |
| 144 example_zips.extend( | |
| 145 root + '.zip' for name in files if name == manifest_json) | |
| 146 logging.info('cron: rendering %s example zips...' % len(example_zips)) | |
| 147 start_time = time.time() | |
| 148 try: | |
| 149 success = success and all( | |
| 150 get_via_render_servlet('extensions/examples/%s' % z).status == 200 | |
| 151 for z in example_zips) | |
| 152 finally: | |
| 153 logging.info('cron: rendering %s example zips took %s seconds' % ( | |
| 154 len(example_zips), time.time() - start_time)) | |
| 155 | 117 |
| 156 except DeadlineExceededError: | 118 # Extension examples have zip files too. Well, so do apps, but the app |
| 157 success = False | 119 # file system doesn't get the Offline treatment so they don't need cron. |
| 120 if not IsDevServer(): | |
| 121 manifest_json = 'manifest.json' | |
| 122 example_zips = [] | |
| 123 for root, _, files in server_instance.host_file_system.Walk( | |
| 124 svn_constants.EXAMPLES_PATH): | |
| 125 example_zips.extend( | |
| 126 root + '.zip' for name in files if name == manifest_json) | |
| 127 logging.info('cron: rendering %s example zips...' % len(example_zips)) | |
| 128 start_time = time.time() | |
| 129 try: | |
| 130 success = success and all( | |
| 131 get_via_render_servlet('extensions/examples/%s' % z).status == 200 | |
| 132 for z in example_zips) | |
| 133 finally: | |
| 134 logging.info('cron: rendering %s example zips took %s seconds' % ( | |
| 135 len(example_zips), time.time() - start_time)) | |
| 158 | 136 |
| 159 logging.info('cron: running Redirector cron...') | 137 logging.info('cron: running Redirector cron...') |
| 160 server_instance.redirector.Cron() | 138 server_instance.redirector.Cron() |
| 161 | 139 |
| 162 logging.info('cron: finished (%s)' % ('success' if success else 'failure',)) | 140 logging.info('cron: finished (%s)' % ('success' if success else 'failure',)) |
| 163 | 141 |
| 164 return (Response.Ok('Success') if success else | 142 return (Response.Ok('Success') if success else |
| 165 Response.InternalError('Failure')) | 143 Response.InternalError('Failure')) |
| 166 | 144 |
| 167 def _GetSafeServerInstance(self): | 145 def _GetSafeServerInstance(self): |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 204 compiled_host_fs_factory = CompiledFileSystem.Factory( | 182 compiled_host_fs_factory = CompiledFileSystem.Factory( |
| 205 host_file_system, | 183 host_file_system, |
| 206 object_store_creator) | 184 object_store_creator) |
| 207 return ServerInstance(object_store_creator, | 185 return ServerInstance(object_store_creator, |
| 208 host_file_system, | 186 host_file_system, |
| 209 app_samples_file_system, | 187 app_samples_file_system, |
| 210 '', | 188 '', |
| 211 compiled_host_fs_factory, | 189 compiled_host_fs_factory, |
| 212 branch_utility, | 190 branch_utility, |
| 213 host_file_system_creator) | 191 host_file_system_creator) |
| OLD | NEW |