Multiple matches created when users join rapidly

Hey Heroic,

We’re using a FindMatch RPC function to create matches based on a provided room identifier. Users with the same room identifier need to connect to the same match. The room identifier is set as a label to the match. This is working fine when users are joining slowly. Unfortunately when users are joining rapidly, multiple matches with the same room identifier are created. This results in users ending up in the wrong match.

We’ve debugged this issue and it seems that the matchList function is not returning the newly created match. We first thought this was due to latency between Nakama and SQL, but I think both the matchList and MatchCreate functions are working with in-memory data.

How can we fix this issue?

Our RPC function:

  • Find match with nk.matchList with the provided room identifier
  • If no matches are found, create a new match with nk.matchCreate
  • Return the match found or the created match

Nakama Version: 3.12.0
Runtime Language: TypeScript

  if (!ctx.userId) {
    throw Error('No user ID in context');
  }

  if (!payload) {
    throw Error('Expects payload.');
  }

  let request = {} as IRpcFindMatchRequest;
  try {
    request = JSON.parse(payload);
  } catch (error) {
    logger.error('Error parsing json message: %q', error);
    throw error;
  }

  let matches: nkruntime.Match[];
  try {
    const query = `+label.open:1 +label.roomId:${request.roomId}`;
    matches = nk.matchList(1, true, null, null, 12, query);
  } catch (error) {
    logger.error('Error listing matches: %v', error);
    throw error;
  }

  if (matches.length === 0) {
    const matchId = nk.matchCreate(serverSettings.moduleName, { roomId: request.roomId });

    const matchIds = [matchId];

    const res: IRpcFindMatchResponse = { matchIds };
    return JSON.stringify(res);
  }

  let matchIds: string[] = [];
  matchIds = matches.map((m) => m.matchId);

  const res: IRpcFindMatchResponse = { matchIds };
  return JSON.stringify(res);

What you’re seeing is due to the delay between a match being created, and the batch processing of the match label indexer. Until the label is indexed it won’t be available to search through via match listing operations.

You have 2 options:

  1. Get the players together in an intermediate lobby first. This might be a party, or a chat channel, or whatever. A simple chat channel might work best as you can base the channel name on your known “room identifier”. They can then agree on one client to create the match, and share the ID with the others.
  2. Reduce the default 1 second indexing window to whatever value you’re comfortable with to achieve the result. Note that this will increase CPU usage. (Look for the match.label_update_interval_ms config option.)

Out of the above I’d probably recommend option 1 to work best no matter what.

Thanks a lot for the quick reply. I wasn’t aware of the batch processing, this makes a lot of sense. We’ll implement one of the solutions.

Have a great day! :slight_smile: