Chromium Code Reviews| Index: chrome/common/extensions/docs/server2/cron_servlet.py |
| diff --git a/chrome/common/extensions/docs/server2/cron_servlet.py b/chrome/common/extensions/docs/server2/cron_servlet.py |
| index e768aa373132597a4186bd877003356d4260f064..f823988c995689aaf82c694f86607bbed66afc1a 100644 |
| --- a/chrome/common/extensions/docs/server2/cron_servlet.py |
| +++ b/chrome/common/extensions/docs/server2/cron_servlet.py |
| @@ -6,16 +6,61 @@ import logging |
| import time |
| import traceback |
| -from appengine_wrappers import DeadlineExceededError, logservice |
| +from appengine_wrappers import DeadlineExceededError, IsDevServer, logservice |
| from branch_utility import BranchUtility |
| +from caching_file_system import CachingFileSystem |
| +from github_file_system import GithubFileSystem |
| +from object_store_creator import ObjectStoreCreator |
| from render_servlet import RenderServlet |
| from server_instance import ServerInstance |
| from servlet import Servlet, Request, Response |
| +from subversion_file_system import SubversionFileSystem |
| import svn_constants |
| +from third_party.json_schema_compiler.memoize import memoize |
| + |
| +def _CreateServerInstanceForChannel(channel, delegate): |
| + object_store_creator = ObjectStoreCreator(channel, start_empty=True) |
| + branch = (delegate.CreateBranchUtility(object_store_creator) |
| + .GetBranchForChannel(channel)) |
| + host_file_system = CachingFileSystem( |
| + delegate.CreateHostFileSystemForBranch(branch), |
| + object_store_creator) |
| + app_samples_file_system = delegate.CreateAppSamplesFileSystem( |
| + object_store_creator) |
| + return ServerInstance(channel, |
| + object_store_creator, |
| + host_file_system, |
| + app_samples_file_system) |
| + |
| +class _SingletonRenderServletDelegate(RenderServlet.Delegate): |
| + def __init__(self, server_instance): |
| + self._server_instance = server_instance |
| + |
| + def CreateServerInstanceForChannel(self, channel): |
| + return self._server_instance |
| class CronServlet(Servlet): |
| '''Servlet which runs a cron job. |
| ''' |
| + def __init__(self, request, delegate_for_test=None): |
| + Servlet.__init__(self, request) |
| + self._delegate = delegate_for_test or CronServlet.Delegate() |
| + |
| + class Delegate(object): |
| + '''Allow runtime dependencies to be overridden for testing. |
| + ''' |
| + def CreateBranchUtility(self, object_store_creator): |
| + return BranchUtility.Create(object_store_creator) |
| + |
| + def CreateHostFileSystemForBranch(self, branch): |
| + return SubversionFileSystem.Create(branch) |
| + |
| + def CreateAppSamplesFileSystem(self, object_store_creator): |
| + # TODO(kalman): CachingFileSystem wrapper for GithubFileSystem, but it's |
| + # not supported yet (see comment there). |
| + return (EmptyDirFileSystem() if IsDevServer() else |
| + GithubFileSystem.Create(object_store_creator)) |
| + |
| def Get(self): |
| # Crons often time out, and when they do *and* then eventually try to |
| # flush logs they die. Turn off autoflush and manually do so at the end. |
| @@ -35,7 +80,14 @@ class CronServlet(Servlet): |
| channel = self._request.path.strip('/') |
| logging.info('cron/%s: starting' % channel) |
| - server_instance = ServerInstance.CreateOnline(channel) |
| + # This is returned every time RenderServlet wants to create a new |
| + # ServerInstance. |
| + server_instance = _CreateServerInstanceForChannel(channel, self._delegate) |
| + |
| + def get_via_render_servlet(path): |
| + return RenderServlet( |
| + Request(path, self._request.headers), |
| + _SingletonRenderServletDelegate(server_instance)).Get() |
| def run_cron_for_dir(d, path_prefix=''): |
| success = True |
| @@ -49,8 +101,7 @@ class CronServlet(Servlet): |
| error = None |
| path = '%s%s' % (path_prefix, f) |
| try: |
| - response = RenderServlet(Request(path, self._request.headers)).Get( |
| - server_instance=server_instance) |
| + response = get_via_render_servlet(path) |
| if response.status != 200: |
| error = 'Got %s response' % response.status |
| except DeadlineExceededError: |
| @@ -70,22 +121,52 @@ class CronServlet(Servlet): |
| return success |
| success = True |
| - for path, path_prefix in ( |
| - # Note: rendering the public templates will pull in all of the private |
| - # templates. |
| - (svn_constants.PUBLIC_TEMPLATE_PATH, ''), |
| - # Note: rendering the public templates will have pulled in the .js and |
| - # manifest.json files (for listing examples on the API reference pages), |
| - # but there are still images, CSS, etc. |
| - (svn_constants.STATIC_PATH, 'static/'), |
| - (svn_constants.EXAMPLES_PATH, 'extensions/examples/')): |
| - try: |
| - # Note: don't try to short circuit any of this stuff. We want to run |
| - # the cron for all the directories regardless of intermediate failures. |
| + try: |
| + # Render all of the publically accessible files. |
|
cduvall
2013/05/08 03:09:14
publically -> publicly
not at google - send to devlin
2013/05/08 18:26:19
Done.
|
| + for path, path_prefix in ( |
| + # Note: rendering the public templates will pull in all of the private |
| + # templates. |
| + (svn_constants.PUBLIC_TEMPLATE_PATH, ''), |
| + # Note: rendering the public templates will have pulled in the .js |
| + # and manifest.json files (for listing examples on the API reference |
| + # pages), but there are still images, CSS, etc. |
| + (svn_constants.STATIC_PATH, 'static/'), |
| + (svn_constants.EXAMPLES_PATH, 'extensions/examples/')): |
| + # Note: don't try to short circuit any of this stuff. We want to run |
| + # the cron for all the directories regardless of intermediate |
| + # failures. |
| success = run_cron_for_dir(path, path_prefix=path_prefix) and success |
| - except DeadlineExceededError: |
| - success = False |
| - break |
| + |
| + # TODO(kalman): Generic way for classes to request cron access. The next |
| + # two special cases are ugly. It would potentially greatly speed up cron |
| + # runs, too. |
| + |
| + # Extension examples have zip files too. Well, so do apps, but the app |
| + # file system doesn't get the Offline treatment so they don't need cron. |
| + manifest_json = '/manifest.json' |
| + example_zips = [ |
| + '%s.zip' % filename[:-len(manifest_json)] |
| + for filename in server_instance.content_cache.GetFromFileListing( |
| + svn_constants.EXAMPLES_PATH) |
| + if filename.endswith(manifest_json)] |
| + logging.info('cron/%s: rendering %s example zips...' % ( |
| + channel, len(example_zips))) |
| + start_time = time.time() |
| + try: |
| + success = success and all( |
| + get_via_render_servlet('extensions/examples/%s' % z).status == 200 |
| + for z in example_zips) |
| + finally: |
| + logging.info('cron/%s: rendering %s example zips took %s seconds' % ( |
| + channel, len(example_zips), time.time() - start_time)) |
| + |
| + # Also trigger a redirect so that PathCanonicalizer has an opportunity to |
| + # cache file listings. |
| + logging.info('cron/%s: triggering a redirect...' % channel) |
| + redirect_response = get_via_render_servlet('storage.html') |
| + success = success and redirect_response.status == 302 |
| + except DeadlineExceededError: |
| + success = False |
| logging.info('cron/%s: finished' % channel) |