add support for subscribing to all message types

This commit is contained in:
gmega 2023-08-24 17:15:07 -03:00
parent 31d7ad731e
commit cb6bc67543
4 changed files with 36 additions and 13 deletions

View File

@ -1,6 +1,7 @@
import engine/protocol
import engine/network
import engine/message
import engine/schedulableevent
import timeutils
export protocol, network, schedulableevent, timeutils
export protocol, network, schedulableevent, message, timeutils

View File

@ -8,6 +8,8 @@ method `messageType`*(self: Message): string {.base.} =
method `messageType`*(self: FreelyTypedMessage): string = self.messageType
proc allMessages*(self: type Message): string = "*"
func typeName(typeDef: NimNode): Option[NimNode] =
expectKind typeDef, nnkTypeDef

View File

@ -24,12 +24,22 @@ proc getProtocol*(self: Peer, id: string): Option[Protocol] =
proc addProtocol*(self: Peer, protocol: Protocol): void =
self.protocols[protocol.id] = protocol
proc deliver*(self: Peer, message: Message, engine: EventDrivenEngine,
network: Network): void =
self.dispatch.getOrDefault(message.messageType, @[]).apply(
proc deliverForType(self: Peer, messageType: string, message: Message,
engine: EventDrivenEngine, network: Network): void =
self.dispatch.getOrDefault(messageType, @[]).apply(
proc (p: Protocol): void = p.deliver(message, engine, network))
proc initPeer(self: Peer, protocols: seq[Protocol]): Peer =
proc deliver*(self: Peer, message: Message, engine: EventDrivenEngine,
network: Network): void =
self.deliverForType(message.messageType, message, engine, network)
self.deliverForType(Message.allMessages, message, engine, network)
proc initPeer*(self: Peer, protocols: seq[Protocol],
peerId: Option[int] = none(int)): Peer =
self.peerId = peerId.get(rand(high(int)))
self.protocols = initTable[string, Protocol]()
self.dispatch = MultiTable[string, Protocol].new()
# XXX integer indexes or an enum would be better, but this is easier
for protocol in protocols:
let protocol = protocol # https://github.com/nim-lang/Nim/issues/16740
@ -47,11 +57,4 @@ proc new*(
protocols: seq[Protocol],
peerId: Option[int] = none(int),
): Peer =
# XXX I can't have put this in the init proc as that would mean allowing public
# write access to every field in Peer. Not sure how to solve this in nim.
let peerId = peerId.get(rand(high(int)))
initPeer(Peer(
protocols: initTable[string, Protocol](),
peerId: peerId,
dispatch: MultiTable[string, Protocol].new()
), protocols)
initPeer(Peer(), protocols, peerId)

View File

@ -4,6 +4,7 @@ import std/sets
import swarmsim/engine/eventdrivenengine
import swarmsim/engine/network
import swarmsim/engine/peer
import swarmsim/engine/message
import ../helpers/inbox
@ -77,3 +78,19 @@ suite "peer":
check(i1.messages == @[m1, m2])
test "should deliver all message types when listening to Message.allMessages":
let i1 = Inbox(id: "protocol1", messageTypes: @[Message.allMessages])
let peer = Peer.new(protocols = @[Protocol i1])
let m1: Message = FreelyTypedMessage(receiver: peer, messageType: "m1")
let m2: Message = FreelyTypedMessage(receiver: peer, messageType: "m2")
let m3: Message = FreelyTypedMessage(receiver: peer, messageType: "m3")
peer.deliver(m1, engine, network)
peer.deliver(m2, engine, network)
peer.deliver(m3, engine, network)
check(i1.messages == @[m1, m2, m3])