Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1190)

Side by Side Diff: chrome/common/extensions/docs/server2/cron_servlet.py

Issue 15009006: Docserver: refactor Servlet, ObjectStore, and ServerInstance architecture to (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix example zipper Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 appengine_wrappers import DeadlineExceededError, logservice 9 from appengine_wrappers import DeadlineExceededError, IsDevServer, logservice
10 from branch_utility import BranchUtility 10 from branch_utility import BranchUtility
11 from caching_file_system import CachingFileSystem
12 from github_file_system import GithubFileSystem
13 from object_store_creator import ObjectStoreCreator
11 from render_servlet import RenderServlet 14 from render_servlet import RenderServlet
12 from server_instance import ServerInstance 15 from server_instance import ServerInstance
13 from servlet import Servlet, Request, Response 16 from servlet import Servlet, Request, Response
17 from subversion_file_system import SubversionFileSystem
14 import svn_constants 18 import svn_constants
19 from third_party.json_schema_compiler.memoize import memoize
20
21 def _CreateServerInstanceForChannel(channel, delegate):
22 object_store_creator = ObjectStoreCreator(channel, start_empty=True)
23 branch = (delegate.CreateBranchUtility(object_store_creator)
24 .GetBranchForChannel(channel))
25 host_file_system = CachingFileSystem(
26 delegate.CreateHostFileSystemForBranch(branch),
27 object_store_creator)
28 app_samples_file_system = delegate.CreateAppSamplesFileSystem(
29 object_store_creator)
30 return ServerInstance(channel,
31 object_store_creator,
32 host_file_system,
33 app_samples_file_system)
34
35 class _SingletonRenderServletDelegate(RenderServlet.Delegate):
36 def __init__(self, server_instance):
37 self._server_instance = server_instance
38
39 def CreateServerInstanceForChannel(self, channel):
40 return self._server_instance
15 41
16 class CronServlet(Servlet): 42 class CronServlet(Servlet):
17 '''Servlet which runs a cron job. 43 '''Servlet which runs a cron job.
18 ''' 44 '''
45 def __init__(self, request, delegate_for_test=None):
46 Servlet.__init__(self, request)
47 self._delegate = delegate_for_test or CronServlet.Delegate()
48
49 class Delegate(object):
50 '''Allow runtime dependencies to be overridden for testing.
51 '''
52 def CreateBranchUtility(self, object_store_creator):
53 return BranchUtility.Create(object_store_creator)
54
55 def CreateHostFileSystemForBranch(self, branch):
56 return SubversionFileSystem.Create(branch)
57
58 def CreateAppSamplesFileSystem(self, object_store_creator):
59 # TODO(kalman): CachingFileSystem wrapper for GithubFileSystem, but it's
60 # not supported yet (see comment there).
61 return (EmptyDirFileSystem() if IsDevServer() else
62 GithubFileSystem.Create(object_store_creator))
63
19 def Get(self): 64 def Get(self):
20 # Crons often time out, and when they do *and* then eventually try to 65 # Crons often time out, and when they do *and* then eventually try to
21 # flush logs they die. Turn off autoflush and manually do so at the end. 66 # flush logs they die. Turn off autoflush and manually do so at the end.
22 logservice.AUTOFLUSH_ENABLED = False 67 logservice.AUTOFLUSH_ENABLED = False
23 try: 68 try:
24 return self._GetImpl() 69 return self._GetImpl()
25 finally: 70 finally:
26 logservice.flush() 71 logservice.flush()
27 72
28 def _GetImpl(self): 73 def _GetImpl(self):
29 # Cron strategy: 74 # Cron strategy:
30 # 75 #
31 # Find all public template files and static files, and render them. Most of 76 # Find all public template files and static files, and render them. Most of
32 # the time these won't have changed since the last cron run, so it's a 77 # the time these won't have changed since the last cron run, so it's a
33 # little wasteful, but hopefully rendering is really fast (if it isn't we 78 # little wasteful, but hopefully rendering is really fast (if it isn't we
34 # have a problem). 79 # have a problem).
35 channel = self._request.path.strip('/') 80 channel = self._request.path.strip('/')
36 logging.info('cron/%s: starting' % channel) 81 logging.info('cron/%s: starting' % channel)
37 82
38 server_instance = ServerInstance.CreateOnline(channel) 83 # This is returned every time RenderServlet wants to create a new
84 # ServerInstance.
85 server_instance = _CreateServerInstanceForChannel(channel, self._delegate)
86
87 def get_via_render_servlet(path):
88 return RenderServlet(
89 Request(path, self._request.headers),
90 _SingletonRenderServletDelegate(server_instance)).Get()
39 91
40 def run_cron_for_dir(d, path_prefix=''): 92 def run_cron_for_dir(d, path_prefix=''):
41 success = True 93 success = True
42 start_time = time.time() 94 start_time = time.time()
43 files = [f for f in server_instance.content_cache.GetFromFileListing(d) 95 files = [f for f in server_instance.content_cache.GetFromFileListing(d)
44 if not f.endswith('/')] 96 if not f.endswith('/')]
45 logging.info('cron/%s: rendering %s files from %s...' % ( 97 logging.info('cron/%s: rendering %s files from %s...' % (
46 channel, len(files), d)) 98 channel, len(files), d))
47 try: 99 try:
48 for i, f in enumerate(files): 100 for i, f in enumerate(files):
49 error = None 101 error = None
50 path = '%s%s' % (path_prefix, f) 102 path = '%s%s' % (path_prefix, f)
51 try: 103 try:
52 response = RenderServlet(Request(path, self._request.headers)).Get( 104 response = get_via_render_servlet(path)
53 server_instance=server_instance)
54 if response.status != 200: 105 if response.status != 200:
55 error = 'Got %s response' % response.status 106 error = 'Got %s response' % response.status
56 except DeadlineExceededError: 107 except DeadlineExceededError:
57 logging.error( 108 logging.error(
58 'cron/%s: deadline exceeded rendering %s (%s of %s): %s' % ( 109 'cron/%s: deadline exceeded rendering %s (%s of %s): %s' % (
59 channel, path, i + 1, len(files), traceback.format_exc())) 110 channel, path, i + 1, len(files), traceback.format_exc()))
60 raise 111 raise
61 except error: 112 except error:
62 pass 113 pass
63 if error: 114 if error:
64 logging.error('cron/%s: error rendering %s: %s' % ( 115 logging.error('cron/%s: error rendering %s: %s' % (
65 channel, path, error)) 116 channel, path, error))
66 success = False 117 success = False
67 finally: 118 finally:
68 logging.info('cron/%s: rendering %s files from %s took %s seconds' % ( 119 logging.info('cron/%s: rendering %s files from %s took %s seconds' % (
69 channel, len(files), d, time.time() - start_time)) 120 channel, len(files), d, time.time() - start_time))
70 return success 121 return success
71 122
72 success = True 123 success = True
73 for path, path_prefix in ( 124 try:
74 # Note: rendering the public templates will pull in all of the private 125 # 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.
75 # templates. 126 for path, path_prefix in (
76 (svn_constants.PUBLIC_TEMPLATE_PATH, ''), 127 # Note: rendering the public templates will pull in all of the private
77 # Note: rendering the public templates will have pulled in the .js and 128 # templates.
78 # manifest.json files (for listing examples on the API reference pages), 129 (svn_constants.PUBLIC_TEMPLATE_PATH, ''),
79 # but there are still images, CSS, etc. 130 # Note: rendering the public templates will have pulled in the .js
80 (svn_constants.STATIC_PATH, 'static/'), 131 # and manifest.json files (for listing examples on the API reference
81 (svn_constants.EXAMPLES_PATH, 'extensions/examples/')): 132 # pages), but there are still images, CSS, etc.
133 (svn_constants.STATIC_PATH, 'static/'),
134 (svn_constants.EXAMPLES_PATH, 'extensions/examples/')):
135 # Note: don't try to short circuit any of this stuff. We want to run
136 # the cron for all the directories regardless of intermediate
137 # failures.
138 success = run_cron_for_dir(path, path_prefix=path_prefix) and success
139
140 # TODO(kalman): Generic way for classes to request cron access. The next
141 # two special cases are ugly. It would potentially greatly speed up cron
142 # runs, too.
143
144 # Extension examples have zip files too. Well, so do apps, but the app
145 # file system doesn't get the Offline treatment so they don't need cron.
146 manifest_json = '/manifest.json'
147 example_zips = [
148 '%s.zip' % filename[:-len(manifest_json)]
149 for filename in server_instance.content_cache.GetFromFileListing(
150 svn_constants.EXAMPLES_PATH)
151 if filename.endswith(manifest_json)]
152 logging.info('cron/%s: rendering %s example zips...' % (
153 channel, len(example_zips)))
154 start_time = time.time()
82 try: 155 try:
83 # Note: don't try to short circuit any of this stuff. We want to run 156 success = success and all(
84 # the cron for all the directories regardless of intermediate failures. 157 get_via_render_servlet('extensions/examples/%s' % z).status == 200
85 success = run_cron_for_dir(path, path_prefix=path_prefix) and success 158 for z in example_zips)
86 except DeadlineExceededError: 159 finally:
87 success = False 160 logging.info('cron/%s: rendering %s example zips took %s seconds' % (
88 break 161 channel, len(example_zips), time.time() - start_time))
162
163 # Also trigger a redirect so that PathCanonicalizer has an opportunity to
164 # cache file listings.
165 logging.info('cron/%s: triggering a redirect...' % channel)
166 redirect_response = get_via_render_servlet('storage.html')
167 success = success and redirect_response.status == 302
168 except DeadlineExceededError:
169 success = False
89 170
90 logging.info('cron/%s: finished' % channel) 171 logging.info('cron/%s: finished' % channel)
91 172
92 return (Response.Ok('Success') if success else 173 return (Response.Ok('Success') if success else
93 Response.InternalError('Failure')) 174 Response.InternalError('Failure'))
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698