Incorrect docs for `MatchSignal`

NOTE: As a new user I can’t post more than 2 links so I will include links to the below mentioned online documentation pages in replies in this thread (btw can an admin remove that restriction for me? Pretty tricky to write thorough posts with only 2 links).

Whilst implementing a match handler I dug a bit deeper on the less-obvious interface functions and couldn’t quite make heads or tails of MatchSignal. This applies to both the match handler interface MatchSignal and Nakama runtime module API runtime.NakamaModule.MatchSignal.

Both of the Go runtime function reference(1) and Go match handler function reference(2) pages say something along the lines of “this is used to reserve a spot for an incoming player ahead of time”, but after a closer look that seems like more of an example use case, is that correct?

Looking at the runtime module API specifically, the online docs(1) and func docs (below) for the id param state that it accepts a user or session ID and an arbitrary string payload. At surface level this doesn’t quite make sense with the provided usage example since the user/session ID wouldn’t be associated with any match instance before the join flow has begun right?
After looking at the implementation it looks like the id param is actually the match ID (more specifically a UUID + node ID for authoritative matches), which makes sense.

Go runtime func definition with seemingly incorrect docs:

LocalMatchRegistry.Signal implementation where match & node ID are extracted:

Considering all that, I have a couple Qs:

  1. Does the runtime MatchSignal take a match ID as the id param rather than a user/session ID or have I missed something? (bit tricky to navigate a codebase on github so I wouldn’t be surprised if I have!)
  2. Can this safely be (ab)used to infrequently send arbitrary data to a match instance? Specifically in single-node (temp dev server) and Heroic Cloud setups. Is the perf impact likely to be an issue at scale?
    • This forum post(3) seems to indicate it can be abused to forward server-to-server RPC comms to a match instance with the caveat that it may negatively impact the match loop. It’s hard to judge how bad it is to rely on this long-term.
    • As an example: we have a hard reliance on a 3rd party cloud service and we rely on data it exposes via webhooks for authoritative match results (one-time) and a chunked data steam (infrequent with configurable interval, anywhere from 2-40 secs). Would this cause issues at high scale on Heroic Cloud? (if this question is more suited to other support channels let me know and I’ll remove it and send it elsewhere)

(1): Function Reference - Heroic Labs Documentation
(2): Match Handler API - Heroic Labs Documentation

(3): Send MatchData From another server - #2 by sesposito

  1. Yes
  2. Abuse or not depends on how you implement it. The best thing to do is get the data from an external service at the start of the match and save the result to the external service when the match finishes.

More about negatively impact the match loop form post 3. All match handlers with a state argument are called one after another (synchronously), rather than asynchronously. This means that if you have a match with a tickrate of 10, and you have 100 milliseconds for all logic, this is not just for the matchloop handler

Thanks for the confirmation and the context around the perf implications, that helps a lot!

While we use Nakama as our lobby system, our actual game server hosting is external and that’s not something we can change (hence the hard reliance). Server-authoritative match results and replay data are received via RPC while the match is running, match signals are probably our best option for getting that data where it needs to be in a timely fashion.

Having said that, we can process the replay data stream separately from the match handler and reduce the number of signals per match to 1. The one-off match results signal perf shouldn’t be an issue for us.

Thanks again!

1 Like