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, IsDevServer, logservice) | 11 GetAppVersion, IsDeadlineExceededError, IsDevServer, 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 file_system_util import CreateURLsFromPaths | 16 from file_system_util import CreateURLsFromPaths |
17 from github_file_system import GithubFileSystem | 17 from github_file_system import GithubFileSystem |
18 from host_file_system_creator import HostFileSystemCreator | 18 from host_file_system_provider import HostFileSystemProvider |
19 from object_store_creator import ObjectStoreCreator | 19 from object_store_creator import ObjectStoreCreator |
20 from render_servlet import RenderServlet | 20 from render_servlet import RenderServlet |
21 from server_instance import ServerInstance | 21 from server_instance import ServerInstance |
22 from servlet import Servlet, Request, Response | 22 from servlet import Servlet, Request, Response |
23 import svn_constants | 23 import svn_constants |
24 | 24 |
25 class _SingletonRenderServletDelegate(RenderServlet.Delegate): | 25 class _SingletonRenderServletDelegate(RenderServlet.Delegate): |
26 def __init__(self, server_instance): | 26 def __init__(self, server_instance): |
27 self._server_instance = server_instance | 27 self._server_instance = server_instance |
28 | 28 |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
83 def __init__(self, request, delegate_for_test=None): | 83 def __init__(self, request, delegate_for_test=None): |
84 Servlet.__init__(self, request) | 84 Servlet.__init__(self, request) |
85 self._delegate = delegate_for_test or CronServlet.Delegate() | 85 self._delegate = delegate_for_test or CronServlet.Delegate() |
86 | 86 |
87 class Delegate(object): | 87 class Delegate(object): |
88 '''CronServlet's runtime dependencies. Override for testing. | 88 '''CronServlet's runtime dependencies. Override for testing. |
89 ''' | 89 ''' |
90 def CreateBranchUtility(self, object_store_creator): | 90 def CreateBranchUtility(self, object_store_creator): |
91 return BranchUtility.Create(object_store_creator) | 91 return BranchUtility.Create(object_store_creator) |
92 | 92 |
93 def CreateHostFileSystemCreator(self, object_store_creator): | 93 def CreateHostFileSystemProvider(self, |
94 return HostFileSystemCreator(object_store_creator) | 94 object_store_creator, |
| 95 max_trunk_revision=None): |
| 96 return HostFileSystemProvider(object_store_creator, |
| 97 max_trunk_revision=max_trunk_revision) |
95 | 98 |
96 def CreateAppSamplesFileSystem(self, object_store_creator): | 99 def CreateAppSamplesFileSystem(self, object_store_creator): |
97 # TODO(kalman): CachingFileSystem wrapper for GithubFileSystem, but it's | 100 # TODO(kalman): CachingFileSystem wrapper for GithubFileSystem, but it's |
98 # not supported yet (see comment there). | 101 # not supported yet (see comment there). |
99 return (EmptyDirFileSystem() if IsDevServer() else | 102 return (EmptyDirFileSystem() if IsDevServer() else |
100 GithubFileSystem.Create(object_store_creator)) | 103 GithubFileSystem.Create(object_store_creator)) |
101 | 104 |
102 def GetAppVersion(self): | 105 def GetAppVersion(self): |
103 return GetAppVersion() | 106 return GetAppVersion() |
104 | 107 |
(...skipping 21 matching lines...) Expand all Loading... |
126 # little wasteful, but hopefully rendering is really fast (if it isn't we | 129 # little wasteful, but hopefully rendering is really fast (if it isn't we |
127 # have a problem). | 130 # have a problem). |
128 _cronlog.info('starting') | 131 _cronlog.info('starting') |
129 | 132 |
130 # This is returned every time RenderServlet wants to create a new | 133 # This is returned every time RenderServlet wants to create a new |
131 # ServerInstance. | 134 # ServerInstance. |
132 # | 135 # |
133 # TODO(kalman): IMPORTANT. This sometimes throws an exception, breaking | 136 # TODO(kalman): IMPORTANT. This sometimes throws an exception, breaking |
134 # everything. Need retry logic at the fetcher level. | 137 # everything. Need retry logic at the fetcher level. |
135 server_instance = self._GetSafeServerInstance() | 138 server_instance = self._GetSafeServerInstance() |
| 139 trunk_fs = server_instance.host_file_system_provider.GetTrunk() |
136 | 140 |
137 def render(path): | 141 def render(path): |
138 request = Request(path, self._request.host, self._request.headers) | 142 request = Request(path, self._request.host, self._request.headers) |
139 delegate = _SingletonRenderServletDelegate(server_instance) | 143 delegate = _SingletonRenderServletDelegate(server_instance) |
140 return RenderServlet(request, delegate).Get() | 144 return RenderServlet(request, delegate).Get() |
141 | 145 |
142 def request_files_in_dir(path, prefix=''): | 146 def request_files_in_dir(path, prefix=''): |
143 '''Requests every file found under |path| in this host file system, with | 147 '''Requests every file found under |path| in this host file system, with |
144 a request prefix of |prefix|. | 148 a request prefix of |prefix|. |
145 ''' | 149 ''' |
146 files = [name for name, _ in | 150 files = [name for name, _ in CreateURLsFromPaths(trunk_fs, path, prefix)] |
147 CreateURLsFromPaths(server_instance.host_file_system, path, prefix)] | |
148 return _RequestEachItem(path, files, render) | 151 return _RequestEachItem(path, files, render) |
149 | 152 |
150 results = [] | 153 results = [] |
151 | 154 |
152 try: | 155 try: |
153 # Rendering the public templates will also pull in all of the private | 156 # Rendering the public templates will also pull in all of the private |
154 # templates. | 157 # templates. |
155 results.append(request_files_in_dir(svn_constants.PUBLIC_TEMPLATE_PATH)) | 158 results.append(request_files_in_dir(svn_constants.PUBLIC_TEMPLATE_PATH)) |
156 | 159 |
157 # Rendering the public templates will have pulled in the .js and | 160 # Rendering the public templates will have pulled in the .js and |
158 # manifest.json files (for listing examples on the API reference pages), | 161 # manifest.json files (for listing examples on the API reference pages), |
159 # but there are still images, CSS, etc. | 162 # but there are still images, CSS, etc. |
160 results.append(request_files_in_dir(svn_constants.STATIC_PATH, | 163 results.append(request_files_in_dir(svn_constants.STATIC_PATH, |
161 prefix='static/')) | 164 prefix='static/')) |
162 | 165 |
163 # Samples are too expensive to run on the dev server, where there is no | 166 # Samples are too expensive to run on the dev server, where there is no |
164 # parallel fetch. | 167 # parallel fetch. |
165 if not IsDevServer(): | 168 if not IsDevServer(): |
166 # Fetch each individual sample file. | 169 # Fetch each individual sample file. |
167 results.append(request_files_in_dir(svn_constants.EXAMPLES_PATH, | 170 results.append(request_files_in_dir(svn_constants.EXAMPLES_PATH, |
168 prefix='extensions/examples/')) | 171 prefix='extensions/examples/')) |
169 | 172 |
170 # Fetch the zip file of each example (contains all the individual | 173 # Fetch the zip file of each example (contains all the individual |
171 # files). | 174 # files). |
172 example_zips = [] | 175 example_zips = [] |
173 for root, _, files in server_instance.host_file_system.Walk( | 176 for root, _, files in trunk_fs.Walk(svn_constants.EXAMPLES_PATH): |
174 svn_constants.EXAMPLES_PATH): | |
175 example_zips.extend( | 177 example_zips.extend( |
176 root + '.zip' for name in files if name == 'manifest.json') | 178 root + '.zip' for name in files if name == 'manifest.json') |
177 results.append(_RequestEachItem( | 179 results.append(_RequestEachItem( |
178 'example zips', | 180 'example zips', |
179 example_zips, | 181 example_zips, |
180 lambda path: render('extensions/examples/' + path))) | 182 lambda path: render('extensions/examples/' + path))) |
181 | 183 |
182 def run_cron(data_source): | 184 def run_cron(data_source): |
183 title = data_source.__class__.__name__ | 185 title = data_source.__class__.__name__ |
184 _cronlog.info('%s: starting' % title) | 186 _cronlog.info('%s: starting' % title) |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
220 # IMPORTANT: Get a ServerInstance pinned to the most recent revision, not | 222 # IMPORTANT: Get a ServerInstance pinned to the most recent revision, not |
221 # HEAD. These cron jobs take a while and run very frequently such that | 223 # HEAD. These cron jobs take a while and run very frequently such that |
222 # there is usually one running at any given time, and eventually a file | 224 # there is usually one running at any given time, and eventually a file |
223 # that we're dealing with will change underneath it, putting the server in | 225 # that we're dealing with will change underneath it, putting the server in |
224 # an undefined state. | 226 # an undefined state. |
225 server_instance_near_head = self._CreateServerInstance( | 227 server_instance_near_head = self._CreateServerInstance( |
226 self._GetMostRecentRevision()) | 228 self._GetMostRecentRevision()) |
227 | 229 |
228 app_yaml_handler = AppYamlHelper( | 230 app_yaml_handler = AppYamlHelper( |
229 svn_constants.APP_YAML_PATH, | 231 svn_constants.APP_YAML_PATH, |
230 server_instance_near_head.host_file_system, | |
231 server_instance_near_head.object_store_creator, | 232 server_instance_near_head.object_store_creator, |
232 server_instance_near_head.host_file_system_creator) | 233 server_instance_near_head.host_file_system_provider) |
233 | 234 |
234 if app_yaml_handler.IsUpToDate(delegate.GetAppVersion()): | 235 if app_yaml_handler.IsUpToDate(delegate.GetAppVersion()): |
235 return server_instance_near_head | 236 return server_instance_near_head |
236 | 237 |
237 # The version in app.yaml is greater than the currently running app's. | 238 # The version in app.yaml is greater than the currently running app's. |
238 # The safe version is the one before it changed. | 239 # The safe version is the one before it changed. |
239 safe_revision = app_yaml_handler.GetFirstRevisionGreaterThan( | 240 safe_revision = app_yaml_handler.GetFirstRevisionGreaterThan( |
240 delegate.GetAppVersion()) - 1 | 241 delegate.GetAppVersion()) - 1 |
241 | 242 |
242 _cronlog.info('app version %s is out of date, safe is %s', | 243 _cronlog.info('app version %s is out of date, safe is %s', |
243 delegate.GetAppVersion(), safe_revision) | 244 delegate.GetAppVersion(), safe_revision) |
244 | 245 |
245 return self._CreateServerInstance(safe_revision) | 246 return self._CreateServerInstance(safe_revision) |
246 | 247 |
247 def _GetMostRecentRevision(self): | 248 def _GetMostRecentRevision(self): |
248 '''Gets the revision of the most recent patch submitted to the host file | 249 '''Gets the revision of the most recent patch submitted to the host file |
249 system. This is similar to HEAD but it's a concrete revision so won't | 250 system. This is similar to HEAD but it's a concrete revision so won't |
250 change as the cron runs. | 251 change as the cron runs. |
251 ''' | 252 ''' |
252 return self._CreateServerInstance(None).host_file_system.Stat('/').version | 253 head_fs = ( |
| 254 self._CreateServerInstance(None).host_file_system_provider.GetTrunk()) |
| 255 return head_fs.Stat('/').version |
253 | 256 |
254 def _CreateServerInstance(self, revision): | 257 def _CreateServerInstance(self, revision): |
255 '''Creates a ServerInstance pinned to |revision|, or HEAD if None. | 258 '''Creates a ServerInstance pinned to |revision|, or HEAD if None. |
256 NOTE: If passed None it's likely that during the cron run patches will be | 259 NOTE: If passed None it's likely that during the cron run patches will be |
257 submitted at HEAD, which may change data underneath the cron run. | 260 submitted at HEAD, which may change data underneath the cron run. |
258 ''' | 261 ''' |
259 object_store_creator = ObjectStoreCreator(start_empty=True) | 262 object_store_creator = ObjectStoreCreator(start_empty=True) |
260 branch_utility = self._delegate.CreateBranchUtility(object_store_creator) | 263 branch_utility = self._delegate.CreateBranchUtility(object_store_creator) |
261 host_file_system_creator = self._delegate.CreateHostFileSystemCreator( | 264 host_file_system_provider = self._delegate.CreateHostFileSystemProvider( |
262 object_store_creator) | 265 object_store_creator, max_trunk_revision=revision) |
263 host_file_system = host_file_system_creator.Create(revision=revision) | |
264 app_samples_file_system = self._delegate.CreateAppSamplesFileSystem( | 266 app_samples_file_system = self._delegate.CreateAppSamplesFileSystem( |
265 object_store_creator) | 267 object_store_creator) |
266 compiled_host_fs_factory = CompiledFileSystem.Factory( | 268 compiled_host_fs_factory = CompiledFileSystem.Factory( |
267 host_file_system, | 269 host_file_system_provider.GetTrunk(), |
268 object_store_creator) | 270 object_store_creator) |
269 return ServerInstance(object_store_creator, | 271 return ServerInstance(object_store_creator, |
270 host_file_system, | |
271 app_samples_file_system, | 272 app_samples_file_system, |
272 compiled_host_fs_factory, | 273 compiled_host_fs_factory, |
273 branch_utility, | 274 branch_utility, |
274 host_file_system_creator) | 275 host_file_system_provider) |
OLD | NEW |