def __init__(self): self._codec = _default_codec() self.lock = threading.Condition() self.events = Queue() self.token_counter = 0 self.sites = {} # host, port -> site self.event_thread = _EventProcessor(self) self.event_thread.daemon = True self.event_thread.start() self._codec = _default_codec() self.log = Logger("quark.runtime")
def logger(self, topic): return Logger(topic)
class ThreadedRuntime(object): def __init__(self): self._codec = _default_codec() self.lock = threading.Condition() self.events = Queue() self.token_counter = 0 self.sites = {} # host, port -> site self.event_thread = _EventProcessor(self) self.event_thread.daemon = True self.event_thread.start() self._codec = _default_codec() self.log = Logger("quark.runtime") def acquire(self): self.lock.acquire() def release(self): self.lock.release() def _notify(self): self.lock.notify_all() def wait(self, timeoutInSeconds): self.lock.wait(timeoutInSeconds) def _add_event_source(self, name): with self.event_thread.token_lock: token = (self.token_counter, name, self) self.token_counter += 1 self.event_thread.live.add(token) return token def _remove_event_source(self, token): def remove_token(): with self.event_thread.token_lock: self.event_thread.live.remove(token) self.events.put((remove_token, (), {})) def open(self, url, handler): def pump_websocket(runtime, url, handler): ws = _QuarkWS(runtime, url, handler) try: ws.connect() ws.run_forever() except Exception as ex: runtime.log.debug("websocket pump exception: %s" % ex) import quark runtime.events.put((handler.onWSError, (ws, quark.WSError(str(ex))), {})) runtime.events.put((handler.onWSFinal, (ws,), {})) try: self.acquire() thread = threading.Thread(target=Tracker(self, "client websocket", pump_websocket), args=(self, url, handler)) thread.setDaemon(True) thread.start() finally: self.release() def request(self, request, handler): try: self.acquire() thread = threading.Thread(target=Tracker(self, "request", _QuarkRequest(self, request, handler))) thread.setDaemon(True) thread.start() finally: self.release() def schedule(self, handler, delayInSeconds): def run_scheduled(runtime, handler, delayInSeconds): time.sleep(delayInSeconds) runtime.events.put((handler.onExecute, [runtime], {})) try: self.acquire() thread = threading.Thread(target=Tracker(self, "task", run_scheduled), args=(self, handler, delayInSeconds)) thread.setDaemon(True) thread.start() finally: self.release() def serveHTTP(self, url, servlet): url = Url(url) import quark if url.scheme not in ["http", "https"]: self.events.put((servlet.onServletError, (url.url, quark.ServletError(url.scheme + " is not supported")), {})) return if url.scheme in ["https"]: self.events.put((servlet.onServletError, (url.url, quark.ServletError(url.scheme + " is not supported yet")), {})) return container = self._make_container(url) container.add(HttpServletAdapter(self, url, servlet)) def serveWS(self, url, servlet): url = Url(url) import quark if url.scheme not in ["ws", "wss"]: self.events.put((servlet.onServletError, (url.url, quark.ServletError(url.scheme + " is not supported")), {})) return if url.scheme in ["wss"]: self.events.put((servlet.onServletError, (url.url, quark.ServletError(url.scheme + " is not supported yet")), {})) return container = self._make_container(url) container.add(WSServletAdapter(self, url, servlet)) def _make_container(self, url): try: with self.lock: server = self.sites.get((url.host, url.port)) if not server: # synchronous bind and listen... server = _QuarkWSGIServer((url.host, url.port), _QuarkWSGIRequestHandler) url.port = server.server_port app = _QuarkWSGIApp(self, url) server.set_app(app) server.initialize_websockets_manager() thread = threading.Thread(target = Tracker(self, "container", server.serve_forever)) thread.setDaemon(True) thread.start() self.sites[url.host, url.port] = server return server.application except Exception as exc: print(traceback.format_exc()) return _NoApplication(self, url, exc) def respond(self, request, response): response._responded = True def fail(self, message): self.event_thread.die_now = True if False: # Set to True to enable traceback printing print("Traceback (most recent call last, up to fail(...)):") traceback.print_stack(sys._getframe(1)) # Note: sys._getframe(1) works on CPython, Jython, and PyPy. Need to test on IronPython etc. sys.stderr.write(message + "\n") os._exit(1) def codec(self): return self._codec def logger(self, topic): return Logger(topic) def now(self): return long(time.time() * 1000) def sleep(self, seconds): time.sleep(seconds) def uuid(self): return str(uuid.uuid4()) def callSafely(self, unary_callable, default): try: import quark return quark.callUnaryCallable(unary_callable, None) except: self.log.error("Exception while calling safely: " + traceback.format_exc()) return default