Beispiel #1
0
 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
Beispiel #2
0
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()