OLD | NEW |
(Empty) | |
| 1 # Copyright 2014 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 import logging |
| 6 import posixpath |
| 7 |
| 8 from custom_logger import CustomLogger |
| 9 from extensions_paths import EXAMPLES |
| 10 from file_system_util import CreateURLsFromPaths |
| 11 from future import Future |
| 12 from render_servlet import RenderServlet |
| 13 from special_paths import SITE_VERIFICATION_FILE |
| 14 from timer import Timer |
| 15 |
| 16 |
| 17 _SUPPORTED_TARGETS = { |
| 18 'examples': (EXAMPLES, 'extensions/examples'), |
| 19 } |
| 20 |
| 21 |
| 22 _log = CustomLogger('render_refresher') |
| 23 |
| 24 |
| 25 class _SingletonRenderServletDelegate(RenderServlet.Delegate): |
| 26 def __init__(self, server_instance): |
| 27 self._server_instance = server_instance |
| 28 |
| 29 def CreateServerInstance(self): |
| 30 return self._server_instance |
| 31 |
| 32 |
| 33 def _RequestEachItem(title, items, request_callback): |
| 34 '''Runs a task |request_callback| named |title| for each item in |items|. |
| 35 |request_callback| must take an item and return a servlet response. |
| 36 Returns true if every item was successfully run, false if any return a |
| 37 non-200 response or raise an exception. |
| 38 ''' |
| 39 _log.info('%s: starting', title) |
| 40 success_count, failure_count = 0, 0 |
| 41 timer = Timer() |
| 42 try: |
| 43 for i, item in enumerate(items): |
| 44 def error_message(detail): |
| 45 return '%s: error rendering %s (%s of %s): %s' % ( |
| 46 title, item, i + 1, len(items), detail) |
| 47 try: |
| 48 response = request_callback(item) |
| 49 if response.status == 200: |
| 50 success_count += 1 |
| 51 else: |
| 52 _log.error(error_message('response status %s' % response.status)) |
| 53 failure_count += 1 |
| 54 except Exception as e: |
| 55 _log.error(error_message(traceback.format_exc())) |
| 56 failure_count += 1 |
| 57 if IsDeadlineExceededError(e): raise |
| 58 finally: |
| 59 _log.info('%s: rendered %s of %s with %s failures in %s', |
| 60 title, success_count, len(items), failure_count, |
| 61 timer.Stop().FormatElapsed()) |
| 62 return success_count == len(items) |
| 63 |
| 64 |
| 65 class RenderRefresher(object): |
| 66 '''Used to refresh any set of renderable resources. Currently only supports |
| 67 assets related to extensions examples.''' |
| 68 def __init__(self, server_instance, request): |
| 69 self._server_instance = server_instance |
| 70 self._request = request |
| 71 |
| 72 def GetRefreshPaths(self): |
| 73 return _SUPPORTED_TARGETS.keys() |
| 74 |
| 75 def Refresh(self, path): |
| 76 def render(path): |
| 77 request = Request(path, self._request.host, self._request.headers) |
| 78 delegate = _SingletonRenderServletDelegate(self._server_instance) |
| 79 return RenderServlet(request, delegate).Get() |
| 80 |
| 81 def request_files_in_dir(path, prefix='', strip_ext=None): |
| 82 '''Requests every file found under |path| in this host file system, with |
| 83 a request prefix of |prefix|. |strip_ext| is an optional list of file |
| 84 extensions that should be stripped from paths before requesting. |
| 85 ''' |
| 86 def maybe_strip_ext(name): |
| 87 if name == SITE_VERIFICATION_FILE or not strip_ext: |
| 88 return name |
| 89 base, ext = posixpath.splitext(name) |
| 90 return base if ext in strip_ext else name |
| 91 files = [maybe_strip_ext(name) |
| 92 for name, _ in CreateURLsFromPaths(master_fs, path, prefix)] |
| 93 return _RequestEachItem(path, files, render) |
| 94 |
| 95 # Only support examples for now. |
| 96 if path not in _SUPPORTED_TARGETS: |
| 97 return Future(callback=lambda: False) |
| 98 |
| 99 dir = _SUPPORTED_TARGETS[path][0] |
| 100 prefix = _SUPPORTED_TARGETS[path][1] |
| 101 return request_files_in_dir(dir, prefix=prefix) |
OLD | NEW |