Index: gm/rebaseline_server/server.py |
=================================================================== |
--- gm/rebaseline_server/server.py (revision 12499) |
+++ gm/rebaseline_server/server.py (working copy) |
@@ -62,6 +62,10 @@ |
DEFAULT_ACTUALS_DIR = '.gm-actuals' |
DEFAULT_PORT = 8888 |
+# How often (in seconds) clients should reload while waiting for initial |
+# results to load. |
+RELOAD_INTERVAL_UNTIL_READY = 10 |
+ |
_HTTP_HEADER_CONTENT_LENGTH = 'Content-Length' |
_HTTP_HEADER_CONTENT_TYPE = 'Content-Type' |
@@ -213,18 +217,24 @@ |
expected_root=EXPECTATIONS_DIR, |
generated_images_root=GENERATED_IMAGES_ROOT) |
- def _result_reloader(self): |
- """ Reload results at the appropriate interval. This never exits, so it |
- should be run in its own thread. |
+ def _result_loader(self, reload_seconds=0): |
+ """ Call self.update_results(), either once or periodically. |
+ |
+ Params: |
+ reload_seconds: integer; if nonzero, reload results at this interval |
+ (in which case, this method will never return!) |
""" |
- while True: |
- time.sleep(self._reload_seconds) |
- self.update_results() |
+ self.update_results() |
+ logging.info('Initial results loaded. Ready for requests on %s' % self._url) |
+ if reload_seconds: |
+ while True: |
+ time.sleep(reload_seconds) |
+ self.update_results() |
def run(self): |
- self.update_results() |
- if self._reload_seconds: |
- thread.start_new_thread(self._result_reloader, ()) |
+ arg_tuple = (self._reload_seconds,) # start_new_thread needs a tuple, |
+ # even though it holds just one param |
+ thread.start_new_thread(self._result_loader, arg_tuple) |
if self._export: |
server_address = ('', self._port) |
@@ -237,8 +247,8 @@ |
host = '127.0.0.1' |
server_address = (host, self._port) |
http_server = BaseHTTPServer.HTTPServer(server_address, HTTPRequestHandler) |
- logging.info('Ready for requests on http://%s:%d' % ( |
- host, http_server.server_port)) |
+ self._url = 'http://%s:%d' % (host, http_server.server_port) |
+ logging.info('Listening for requests on %s' % self._url) |
http_server.serve_forever() |
@@ -287,10 +297,34 @@ |
# HTTPServer, and then it could be available to the handler via |
# the handler's .server instance variable. |
results_obj = _SERVER.results |
- response_dict = results_obj.get_results_of_type(type) |
- time_updated = results_obj.get_timestamp() |
+ if results_obj: |
+ response_dict = self.package_results(results_obj, type) |
+ else: |
+ now = int(time.time()) |
+ response_dict = { |
+ 'header': { |
+ 'resultsStillLoading': True, |
+ 'timeUpdated': now, |
+ 'timeNextUpdateAvailable': now + RELOAD_INTERVAL_UNTIL_READY, |
+ }, |
+ } |
+ self.send_json_dict(response_dict) |
+ except: |
+ self.send_error(404) |
+ raise |
- response_dict['header'] = { |
+ def package_results(self, results_obj, type): |
+ """ Given a nonempty "results" object, package it as a response_dict |
+ as needed within do_GET_results. |
+ |
+ Args: |
+ results_obj: nonempty "results" object |
+ type: string indicating which set of results to return; |
+ must be one of the results.RESULTS_* constants |
+ """ |
+ response_dict = results_obj.get_results_of_type(type) |
+ time_updated = results_obj.get_timestamp() |
+ response_dict['header'] = { |
# Timestamps: |
# 1. when this data was last updated |
# 2. when the caller should check back for new data (if ever) |
@@ -315,11 +349,8 @@ |
# Whether the service is accessible from other hosts. |
'isExported': _SERVER.is_exported, |
- } |
- self.send_json_dict(response_dict) |
- except: |
- self.send_error(404) |
- raise |
+ } |
+ return response_dict |
def do_GET_static(self, path): |
""" Handle a GET request for a file under the 'static' directory. |