You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
soil/soil/agents/evented.py

59 lines
1.8 KiB
Python

2 years ago
from . import BaseAgent
from ..events import Message, Tell, Ask, TimedOut
2 years ago
from functools import partial
from collections import deque
1 year ago
from types import coroutine
class EventedAgent(BaseAgent):
2 years ago
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._inbox = deque()
self._processed = 0
def on_receive(self, *args, **kwargs):
pass
1 year ago
@coroutine
def received(self, expiration=None, timeout=60, delay=1, process=True):
if not expiration:
expiration = self.now + timeout
while self.now < expiration:
if self._inbox:
msgs = self._inbox
if process:
self.process_messages()
return msgs
yield self.delay(delay)
raise TimedOut("No message received")
2 years ago
def tell(self, msg, sender=None):
self._inbox.append(Tell(timestamp=self.now, payload=msg, sender=sender))
2 years ago
1 year ago
@coroutine
def ask(self, msg, expiration=None, timeout=None, delay=1):
ask = Ask(timestamp=self.now, payload=msg, sender=self)
2 years ago
self._inbox.append(ask)
2 years ago
expiration = float("inf") if timeout is None else self.now + timeout
1 year ago
while self.now < expiration:
if ask.reply:
return ask.reply
yield self.delay(delay)
raise TimedOut("No reply received")
def process_messages(self):
valid = list()
for msg in self._inbox:
2 years ago
self._processed += 1
if msg.expired(self.now):
continue
1 year ago
valid.append(msg)
2 years ago
reply = self.on_receive(msg.payload, sender=msg.sender)
if isinstance(msg, Ask):
msg.reply = reply
1 year ago
self._inbox.clear()
return valid
2 years ago
Evented = EventedAgent