feat: According to the routing feature plan in Chapter 2.2.3.2 of RFC 113, the routing functionality is to be consolidated into the Environment class.

This commit is contained in:
莘权 马 2023-11-04 14:07:33 +08:00
parent 8137e1af50
commit 2688fe680a
3 changed files with 33 additions and 10 deletions

View file

@ -8,9 +8,11 @@
1. Remove the functionality of `Environment` class as a public message buffer.
2. Standardize the message forwarding behavior of the `Environment` class.
3. Add the `is_idle` property.
@Modified By: mashenquan, 2023-11-4. According to the routing feature plan in Chapter 2.2.3.2 of RFC 113, the routing
functionality is to be consolidated into the `Environment` class.
"""
import asyncio
from typing import Iterable
from typing import Iterable, Set
from pydantic import BaseModel, Field
@ -26,6 +28,7 @@ class Environment(BaseModel):
"""
roles: dict[str, Role] = Field(default_factory=dict)
consumers: dict[Role, Set] = Field(default_factory=dict)
class Config:
arbitrary_types_allowed = True
@ -36,6 +39,8 @@ class Environment(BaseModel):
"""
role.set_env(self)
self.roles[role.profile] = role
# According to the routing feature plan in Chapter 2.2.3.2 of RFC 113
self.set_subscribed_tags(role, role.subscribed_tags)
def add_roles(self, roles: Iterable[Role]):
"""增加一批在当前环境的角色
@ -55,17 +60,14 @@ class Environment(BaseModel):
"""
logger.info(f"publish_message: {message.save()}")
found = False
for r in self.roles.values():
if message.is_recipient(r.subscribed_tags):
r.put_message(message)
# According to the routing feature plan in Chapter 2.2.3.2 of RFC 113
for obj, subscribed_tags in self.consumers.items():
if message.is_recipient(subscribed_tags):
obj.put_message(message)
found = True
if not found:
logger.warning(f"Message no recipients: {message.save()}")
# Implemented the functionality related to remote message forwarding as described in RFC 113. Awaiting release.
# if self._parent:
# return self._parent.publish_message(message)
return True
async def run(self, k=1):
@ -100,3 +102,11 @@ class Environment(BaseModel):
if not r.is_idle:
return False
return True
def get_subscribed_tags(self, obj):
"""Get the labels for messages to be consumed by the object."""
return self.consumers.get(obj, {})
def set_subscribed_tags(self, obj, tags):
"""Set the labels for message to be consumed by the object"""
self.consumers[obj] = tags

View file

@ -15,6 +15,8 @@
messages into the Role object's private message receive buffer. There are no other message transmit methods.
5. Standardize the parameters for the `run` function: the `test_message` parameter is used for testing purposes
only. In the normal workflow, you should use `publish_message` or `put_message` to transmit messages.
@Modified By: mashenquan, 2023-11-4. According to the routing feature plan in Chapter 2.2.3.2 of RFC 113, the routing
functionality is to be consolidated into the `Environment` class.
"""
from __future__ import annotations
@ -133,7 +135,7 @@ class Role(Named):
def _watch(self, actions: Iterable[Type[Action]]):
"""Listen to the corresponding behaviors"""
tags = [get_class_name(t) for t in actions]
tags = {get_class_name(t) for t in actions}
self.subscribe(tags)
def subscribe(self, tags: Set[str]):
@ -141,6 +143,8 @@ class Role(Named):
self._rc.watch.update(tags)
# check RoleContext after adding watch actions
self._rc.check(self._role_id)
if self._rc.env: # According to the routing feature plan in Chapter 2.2.3.2 of RFC 113
self._rc.env.set_subscribed_tags(self, self.subscribed_tags)
def _set_state(self, state):
"""Update the current state."""
@ -149,7 +153,8 @@ class Role(Named):
self._rc.todo = self._actions[self._rc.state]
def set_env(self, env: "Environment"):
"""Set the environment in which the role works. The role can talk to the environment and can also receive messages by observing."""
"""Set the environment in which the role works. The role can talk to the environment and can also receive
messages by observing."""
self._rc.env = env
@property

View file

@ -6,7 +6,11 @@
@File : test_role.py
@Modified By: mashenquan, 2023-11-1. In line with Chapter 2.2.1 and 2.2.2 of RFC 116, introduce unit tests for
the utilization of the new message distribution feature in message handling.
@Modified By: mashenquan, 2023-11-4. According to the routing feature plan in Chapter 2.2.3.2 of RFC 113, the routing
functionality is to be consolidated into the `Environment` class.
"""
import uuid
import pytest
from pydantic import BaseModel
@ -64,6 +68,7 @@ async def test_react():
assert role.is_idle
env = Environment()
env.add_role(role)
assert env.get_subscribed_tags(role) == {seed.subscription}
env.publish_message(Message(content="test", tx_to=seed.subscription))
assert not role.is_idle
while not env.is_idle:
@ -74,6 +79,9 @@ async def test_react():
while not env.is_idle:
await env.run()
assert role.is_idle
tag = uuid.uuid4().hex
role.subscribe({tag})
assert env.get_subscribed_tags(role) == {seed.subscription, tag}
if __name__ == "__main__":