| Index: chrome/common/extensions/docs/server2/refresh_servlet.py
|
| diff --git a/chrome/common/extensions/docs/server2/refresh_servlet.py b/chrome/common/extensions/docs/server2/refresh_servlet.py
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..eb8c0642a7a67ccf66f876cd8f9d379da6115f47
|
| --- /dev/null
|
| +++ b/chrome/common/extensions/docs/server2/refresh_servlet.py
|
| @@ -0,0 +1,143 @@
|
| +# Copyright 2014 The Chromium Authors. All rights reserved.
|
| +# Use of this source code is governed by a BSD-style license that can be
|
| +# found in the LICENSE file.
|
| +
|
| +import traceback
|
| +
|
| +from app_yaml_helper import AppYamlHelper
|
| +from appengine_wrappers import IsDeadlineExceededError, logservice
|
| +from branch_utility import BranchUtility
|
| +from compiled_file_system import CompiledFileSystem
|
| +from custom_logger import CustomLogger
|
| +from data_source_registry import CreateDataSource
|
| +from environment import GetAppVersion
|
| +from file_system import IsFileSystemThrottledError
|
| +from future import Future
|
| +from gcs_file_system_provider import CloudStorageFileSystemProvider
|
| +from github_file_system_provider import GithubFileSystemProvider
|
| +from host_file_system_provider import HostFileSystemProvider
|
| +from object_store_creator import ObjectStoreCreator
|
| +from server_instance import ServerInstance
|
| +from servlet import Servlet, Request, Response
|
| +from timer import Timer, TimerClosure
|
| +
|
| +
|
| +
|
| +_log = CustomLogger('refresh')
|
| +
|
| +
|
| +class RefreshServlet(Servlet):
|
| + '''Servlet which refreshes a single data source.
|
| + '''
|
| + def __init__(self, request, delegate_for_test=None):
|
| + Servlet.__init__(self, request)
|
| + self._delegate = delegate_for_test or RefreshServlet.Delegate()
|
| +
|
| + class Delegate(object):
|
| + '''RefreshServlet's runtime dependencies. Override for testing.
|
| + '''
|
| + def CreateBranchUtility(self, object_store_creator):
|
| + return BranchUtility.Create(object_store_creator)
|
| +
|
| + def CreateHostFileSystemProvider(self,
|
| + object_store_creator,
|
| + pinned_commit=None):
|
| + return HostFileSystemProvider(object_store_creator,
|
| + pinned_commit=pinned_commit)
|
| +
|
| + def CreateGithubFileSystemProvider(self, object_store_creator):
|
| + return GithubFileSystemProvider(object_store_creator)
|
| +
|
| + def CreateGCSFileSystemProvider(self, object_store_creator):
|
| + return CloudStorageFileSystemProvider(object_store_creator)
|
| +
|
| + def GetAppVersion(self):
|
| + return GetAppVersion()
|
| +
|
| + def Get(self):
|
| + # Manually flush logs at the end of the run. However, sometimes
|
| + # even that isn't enough, which is why in this file we use the
|
| + # custom logger and make it flush the log every time its used.
|
| + logservice.AUTOFLUSH_ENABLED = False
|
| + try:
|
| + return self._GetImpl()
|
| + except BaseException:
|
| + _log.error('Caught top-level exception! %s', traceback.format_exc())
|
| + finally:
|
| + logservice.flush()
|
| +
|
| + def _GetImpl(self):
|
| + path = self._request.path.strip('/')
|
| + parts = self._request.path.split('/', 1)
|
| + source_name = parts[0]
|
| + if len(parts) == 2:
|
| + source_path = parts[1]
|
| + else:
|
| + source_path = None
|
| +
|
| + _log.info('starting refresh of %s DataSource %s' %
|
| + (source_name, '' if source_path is None else '[%s]' % source_path))
|
| +
|
| + if 'commit' in self._request.arguments:
|
| + commit = self._request.arguments['commit']
|
| + else:
|
| + _log.warning('No commit given; refreshing from master. '
|
| + 'This is probably NOT what you want.')
|
| + commit = None
|
| +
|
| + server_instance = self._CreateServerInstance(commit)
|
| + success = True
|
| + try:
|
| + if source_name == 'platform_bundle':
|
| + data_source = server_instance.platform_bundle
|
| + elif source_name == 'content_providers':
|
| + data_source = server_instance.content_providers
|
| + else:
|
| + data_source = CreateDataSource(source_name, server_instance)
|
| +
|
| + class_name = data_source.__class__.__name__
|
| + refresh_future = data_source.Refresh(source_path)
|
| + assert isinstance(refresh_future, Future), (
|
| + '%s.Refresh() did not return a Future' % class_name)
|
| + timer = Timer()
|
| + try:
|
| + refresh_future.Get()
|
| + except Exception as e:
|
| + _log.error('%s: error %s' % (class_name, traceback.format_exc()))
|
| + success = False
|
| + if IsFileSystemThrottledError(e):
|
| + return Response.ThrottledError('Throttled')
|
| + raise
|
| + finally:
|
| + _log.info('Refreshing %s took %s' %
|
| + (class_name, timer.Stop().FormatElapsed()))
|
| +
|
| + except:
|
| + success = False
|
| + # This should never actually happen.
|
| + _log.error('uncaught error: %s' % traceback.format_exc())
|
| + raise
|
| + finally:
|
| + _log.info('finished (%s)', 'success' if success else 'FAILED')
|
| + return (Response.Ok('Success') if success else
|
| + Response.InternalError('Failure'))
|
| +
|
| + def _CreateServerInstance(self, commit):
|
| + '''Creates a ServerInstance pinned to |commit|, or HEAD if None.
|
| + NOTE: If passed None it's likely that during the cron run patches will be
|
| + submitted at HEAD, which may change data underneath the cron run.
|
| + '''
|
| + object_store_creator = ObjectStoreCreator(start_empty=True)
|
| + branch_utility = self._delegate.CreateBranchUtility(object_store_creator)
|
| + host_file_system_provider = self._delegate.CreateHostFileSystemProvider(
|
| + object_store_creator, pinned_commit=commit)
|
| + github_file_system_provider = self._delegate.CreateGithubFileSystemProvider(
|
| + object_store_creator)
|
| + gcs_file_system_provider = self._delegate.CreateGCSFileSystemProvider(
|
| + object_store_creator)
|
| + return ServerInstance(object_store_creator,
|
| + CompiledFileSystem.Factory(object_store_creator),
|
| + branch_utility,
|
| + host_file_system_provider,
|
| + github_file_system_provider,
|
| + gcs_file_system_provider)
|
|
|