def _read_response(self, index, timeout): rs = AsyncResult() self._resps[index] = rs resp = rs.wait(timeout) self._resps.pop(index, None) if not rs.successful(): error = rs.exception if error is None: error = Timeout raise error return resp
class MsgBase(MsgSender,MsgReceiver): """A message which expects a reply.""" timeout = None blocking = False # True if the message needs a reply before sending more _timer = None _last_channel = None _send_err = None _recv_err = None def __init__(self,*a,**k): super(MsgBase,self).__init__(*a,**k) self.result = AsyncResult() def abort(self): if not self.result.ready(): self.result.set(RuntimeError("aborted")) super(MsgBase,self).abort() def list(self): s = super(MsgBase,self) if hasattr(s,'list'): yield s if self.timeout: yield("timeout",self.timeout) if self.result.ready(): try: yield("result",self.result.get()) except Exception as ex: yield("error",repr(ex)) else: yield("status","pending") def send(self,channel): """write myself to the channel. Return None|SEND_AGAIN|RECV_AGAIN.""" self._set_timeout() self._last_channel = channel if self._send_err is None: self._send_err = MSG_ERROR("You need to override %s.send"%self.__class__.__name__) return self._send_err def recv(self,data): """A message has been received. Return NOT_MINE|MINE|RECV_AGAIN|SEND_AGAIN.""" self._clear_timeout() if self._recv_err is None: self._recv_err = MSG_ERROR("You need to override %s.recv"%self.__class__.__name__) return self._recv_err def retry(self): """Check whether to retry this message""" self._clear_timeout() return SEND_AGAIN def done(self): """Processing is finished.""" self._clear_timeout() if self.result is not None and not self.result.successful(): raise RuntimeError("Did not trigger the result in %s.dataReceived()"%(self.__class__.__name__,)) def do_timeout(self): if self._last_channel is not None: self._last_channel.close() self._last_channel = None def _set_timeout(self): if self.timeout is not None: self._timer = callLater(True,self.timeout,self._timeout) def _clear_timeout(self): if self._timer is not None: self._timer.cancel() self._timer = None def _timeout(self): self._timer = None self.do_timeout()