Home | History | Annotate | Download | only in server2
      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 
      5 from appengine_wrappers import IsDevServer
      6 from branch_utility import BranchUtility
      7 from compiled_file_system import CompiledFileSystem
      8 from empty_dir_file_system import EmptyDirFileSystem
      9 from github_file_system import GithubFileSystem
     10 from host_file_system_creator import HostFileSystemCreator
     11 from third_party.json_schema_compiler.memoize import memoize
     12 from render_servlet import RenderServlet
     13 from object_store_creator import ObjectStoreCreator
     14 from server_instance import ServerInstance
     15 
     16 class OfflineRenderServletDelegate(RenderServlet.Delegate):
     17   '''AppEngine instances should never need to call out to SVN. That should only
     18   ever be done by the cronjobs, which then write the result into DataStore,
     19   which is as far as instances look. To enable this, crons can pass a custom
     20   (presumably online) ServerInstance into Get().
     21 
     22   Why? SVN is slow and a bit flaky. Cronjobs failing is annoying but temporary.
     23   Instances failing affects users, and is really bad.
     24 
     25   Anyway - to enforce this, we actually don't give instances access to SVN.  If
     26   anything is missing from datastore, it'll be a 404. If the cronjobs don't
     27   manage to catch everything - uhoh. On the other hand, we'll figure it out
     28   pretty soon, and it also means that legitimate 404s are caught before a round
     29   trip to SVN.
     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     host_file_system_creator = self._delegate.CreateHostFileSystemCreator(
     39         object_store_creator)
     40     host_file_system = host_file_system_creator.Create()
     41     app_samples_file_system = self._delegate.CreateAppSamplesFileSystem(
     42         object_store_creator)
     43     compiled_host_fs_factory = CompiledFileSystem.Factory(
     44         host_file_system,
     45         object_store_creator)
     46     return ServerInstance(object_store_creator,
     47                           host_file_system,
     48                           app_samples_file_system,
     49                           '',
     50                           compiled_host_fs_factory,
     51                           branch_utility,
     52                           host_file_system_creator)
     53 
     54 class 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 CreateHostFileSystemCreator(self, object_store_creator):
     66       return HostFileSystemCreator(object_store_creator, offline=True)
     67 
     68     def CreateAppSamplesFileSystem(self, object_store_creator):
     69       # TODO(kalman): OfflineServerInstance wrapper for GithubFileSystem, but
     70       # the cron job doesn't crawl the samples yet.
     71       return (EmptyDirFileSystem() if IsDevServer() else
     72               GithubFileSystem.Create(object_store_creator))
     73 
     74   @staticmethod
     75   def GetConstructor(delegate_for_test=None):
     76     render_servlet_delegate = OfflineRenderServletDelegate(
     77         delegate_for_test or InstanceServlet.Delegate())
     78     return lambda request: RenderServlet(request, render_servlet_delegate)
     79 
     80   # NOTE: if this were a real Servlet it would implement a Get() method, but
     81   # GetConstructor returns an appropriate lambda function (Request -> Servlet).
     82