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 3# found in the LICENSE file. 4 5from branch_utility import BranchUtility 6from compiled_file_system import CompiledFileSystem 7from environment import IsDevServer, IsReleaseServer 8from github_file_system_provider import GithubFileSystemProvider 9from host_file_system_provider import HostFileSystemProvider 10from third_party.json_schema_compiler.memoize import memoize 11from render_servlet import RenderServlet 12from object_store_creator import ObjectStoreCreator 13from server_instance import ServerInstance 14from gcs_file_system_provider import CloudStorageFileSystemProvider 15 16class InstanceServletRenderServletDelegate(RenderServlet.Delegate): 17 '''AppEngine instances should never need to call out to Gitiles. That should 18 only ever be done by the cronjobs, which then write the result into 19 DataStore, which is as far as instances look. To enable this, crons can pass 20 a custom (presumably online) ServerInstance into Get(). 21 22 Why? Gitiles is slow and a bit flaky. Refresh jobs failing is annoying but 23 temporary. Instances failing affects users, and is really bad. 24 25 Anyway - to enforce this, we actually don't give instances access to 26 Gitiles. If anything is missing from datastore, it'll be a 404. If the 27 cronjobs don't manage to catch everything - uhoh. On the other hand, we'll 28 figure it out pretty soon, and it also means that legitimate 404s are caught 29 before a round trip to Gitiles. 30 ''' 31 def __init__(self, delegate): 32 self._delegate = delegate 33 34 @memoize 35 def CreateServerInstance(self): 36 object_store_creator = ObjectStoreCreator(start_empty=False) 37 branch_utility = self._delegate.CreateBranchUtility(object_store_creator) 38 # In production have offline=True so that we can catch cron errors. In 39 # development it's annoying to have to run the cron job, so offline=False. 40 # Note that offline=True if running on any appengine server due to 41 # http://crbug.com/345361. 42 host_file_system_provider = self._delegate.CreateHostFileSystemProvider( 43 object_store_creator, 44 offline=not (IsDevServer() or IsReleaseServer())) 45 github_file_system_provider = self._delegate.CreateGithubFileSystemProvider( 46 object_store_creator) 47 return ServerInstance(object_store_creator, 48 CompiledFileSystem.Factory(object_store_creator), 49 branch_utility, 50 host_file_system_provider, 51 github_file_system_provider, 52 CloudStorageFileSystemProvider(object_store_creator)) 53 54class InstanceServlet(object): 55 '''Servlet for running on normal AppEngine instances. 56 Create this via GetConstructor() so that cache state can be shared amongst 57 them via the memoizing Delegate. 58 ''' 59 class Delegate(object): 60 '''Allow runtime dependencies to be overriden for testing. 61 ''' 62 def CreateBranchUtility(self, object_store_creator): 63 return BranchUtility.Create(object_store_creator) 64 65 def CreateHostFileSystemProvider(self, object_store_creator, **optargs): 66 return HostFileSystemProvider(object_store_creator, **optargs) 67 68 def CreateGithubFileSystemProvider(self, object_store_creator): 69 return GithubFileSystemProvider(object_store_creator) 70 71 @staticmethod 72 def GetConstructor(delegate_for_test=None): 73 render_servlet_delegate = InstanceServletRenderServletDelegate( 74 delegate_for_test or InstanceServlet.Delegate()) 75 return lambda request: RenderServlet(request, render_servlet_delegate) 76 77 # NOTE: if this were a real Servlet it would implement a Get() method, but 78 # GetConstructor returns an appropriate lambda function (Request -> Servlet). 79