make members attribute only contain ids, not objects

This commit is contained in:
holger krekel
2024-12-16 21:58:34 +01:00
parent 90f49a04e8
commit 0e9076db00

View File

@@ -6,29 +6,34 @@ def relay():
return Relay() return Relay()
def repr_peers(peers):
return ",".join(p.id for p in peers)
class Relay: class Relay:
def __init__(self): def __init__(self):
self.peers = [] self.peers = {}
self.clock = 1
def time(self):
self.clock += 1
return self.clock
def make_peers(self, num): def make_peers(self, num):
newpeers = [Peer(self, i) for i in range(num)] for i in range(num):
self.peers.extend(newpeers) newpeer = Peer(relay=self, num=i)
return newpeers self.peers[newpeer.id] = newpeer
return self.peers.values()
def receive_all(self, peers=None): def receive_all(self, peers=None):
peers = peers if peers else self.peers peers = peers if peers else list(self.peers.values())
for peer in peers: for peer in peers:
for from_peer in self.peers: # drain peer mailbox by reading messages from each sender separately
drain_mailbox(peer, from_peer) for from_peer in self.peers.values():
for msg in peer.from2mailbox.get(from_peer, []):
msg.receive_imf(peer)
def assert_same_members(self): def assert_same_members(self):
for peer1, peer2 in zip(self.peers, self.peers[1:]): peers = list(self.peers.values())
for peer1, peer2 in zip(peers, peers[1:]):
assert peer1.members == peer2.members assert peer1.members == peer2.members
nums = repr_peers(peer1.members) nums = ",".join(peer1.members)
print(f"{peer1.id} and {peer2.id} have same members {nums}") print(f"{peer1.id} and {peer2.id} have same members {nums}")
@@ -36,14 +41,18 @@ class Message:
def __init__(self, sender, **payload): def __init__(self, sender, **payload):
self.sender = sender self.sender = sender
self.recipients = list(sender.members) self.recipients = list(sender.members)
self.relay = sender.relay
self.payload = payload self.payload = payload
def __repr__(self): def __repr__(self):
nums = repr_peers(self.recipients) nums = ",".join(self.recipients)
return f"<{self.__class__.__name__} {self.sender.id}->{nums} {self.payload}" return f"<{self.__class__.__name__} {self.sender.id}->{nums} {self.payload}"
def send(self): def send(self):
for peer in self.sender.members: relay = self.sender.relay
self.payload["sender_clock"] = relay.time()
for peer_id in self.sender.members:
peer = relay.peers[peer_id]
peer.from2mailbox.setdefault(self.sender, []).append(self) peer.from2mailbox.setdefault(self.sender, []).append(self)
@@ -81,36 +90,26 @@ class Peer:
return int(self.id[1:]) return int(self.id[1:])
def __repr__(self): def __repr__(self):
return f"<Peer {self.id} members={repr_peers(self.members)}>" return f"<Peer {self.id} members={','.join(self.members)}>"
def immediate_create_group(self, peers): def immediate_create_group(self, peers):
assert not self.members assert not self.members
self.members.add(self) self.members.add(self.id)
for peer in peers: for peer in peers:
self.add_member(peer) self.add_member(peer)
self.relay.receive_all() self.relay.receive_all()
def add_member(self, newmember): def add_member(self, newmember):
self.members.add(newmember) self.members.add(newmember.id)
message = AddMemberMessage(self, newmember=newmember) AddMemberMessage(self, newmember=newmember.id).send()
message.send()
def del_member(self, member): def del_member(self, member):
message = DelMemberMessage(self, member=member) assert member.id in self.members
message.send() DelMemberMessage(self, member=member.id).send()
self.members.remove(member) self.members.remove(member.id)
def send_chatmessage(self): def send_chatmessage(self):
message = ChatMessage(self) ChatMessage(self).send()
message.send()
### processing group membership message
def drain_mailbox(peer, from_peer):
for msg in peer.from2mailbox.get(from_peer, []):
msg.receive_imf(peer)
### Tests ### Tests
@@ -121,7 +120,7 @@ def test_add_and_remove(relay):
# create group # create group
p0.immediate_create_group([p1]) p0.immediate_create_group([p1])
assert p0.members == p1.members == set([p0, p1]) assert p0.members == p1.members == set([p0.id, p1.id])
# add members # add members
p0.add_member(p2) p0.add_member(p2)
@@ -171,4 +170,4 @@ def test_add_remove_and_stale_old_suddenly_sends(relay):
relay.receive_all() relay.receive_all()
relay.assert_same_members() relay.assert_same_members()
assert p0.members == set([p0, p1, p3]) assert p0.members == set([p0.id, p1.id, p3.id])