Restrict matchmaker to 1 match

Hello,

How do I restrict the matchmaker to not match the player after they’re matched already? For some reason a player was matched 2 times:

{"level":"info","ts":"2025-03-30T09:04:05.869Z","caller":"server/runtime_javascript_logger.go:74","msg":"Battle started: dbb1d0d6-7ecb-421a-a9d2-4dbd6876f13e vs 5716259c-392c-4b1d-8e0d-443ebe4e482c Platinum","mid":"3c32d3fc-5def-4ea0-b483-c8312d649c58"}
{"level":"info","ts":"2025-03-30T09:04:15.950Z","caller":"server/runtime_javascript_logger.go:74","msg":"Battle started: 800f6b1a-84db-485c-8773-7986fdb00819 vs 5716259c-392c-4b1d-8e0d-443ebe4e482c Platinum","mid":"8dc4e388-072e-47ab-9ce1-594d3374a697"}

In my configuration I have max_tickets set to 1 and single_match set to true, I understand that single_match means the previous one receives a leave signal, but how did he get 2 matches in the first place?

single_match will only apply if the user connects to a second match using match_join, disconnecting him from the first.

Likewise, max_tickets should prevent the client from submitting more than 1 ticket within the same session.

Please provide more context on how you’re using the matchmaker, whether you are using authoritative or relayed matches, what custom code you have in place and what the properties and queries look like.

Hello, I’m using authoritative matches with the following hook:

export const beforeMatchmakerAdd: nkruntime.RtBeforeHookFunction<nkruntime.EnvelopeMatchmakerAdd> = function (
  ctx: nkruntime.Context,
  logger: nkruntime.Logger,
  nk: nkruntime.Nakama,
  envelope: nkruntime.EnvelopeMatchmakerAdd
): nkruntime.EnvelopeMatchmakerAdd | void {

  const type = envelope.matchmakerAdd.stringProperties["type"];
  envelope.matchmakerAdd.stringProperties["user"] = ctx.userId;
  envelope.matchmakerAdd.numericProperties = {};

  const res = checkBattle(nk, type, ctx.userId);
  if (!res.success) {
    throw "Invalid team";
  }

  let query = `+properties.type:${type}`;

  if (res.team) envelope.matchmakerAdd.stringProperties["team"] = res.team;

  if (res.maxLevel) {
    query = `${query} +properties.maxLevel:${res.maxLevel}`;
    envelope.matchmakerAdd.numericProperties = { maxLevel: res.maxLevel };
  }

  envelope.matchmakerAdd.query = query;
  envelope.matchmakerAdd.maxCount = 2;
  envelope.matchmakerAdd.minCount = 2;


  logger.info(`Matchmaker add: ${ctx.userId} ${type} ${Date.now()}`);

  return envelope;
};

Are the players not automatically removed from the queue after they join a match? Is there any way for me to remove them?

Can you provide more context on how you’re trying to match the players, and how you’re testing this from the client?

The max_tickets options is per session not per user, so technically the same user can submit two tickets if he’s connecting with different clients, could this be the case?

Matched tickets should be removed from the pool automatically.

I have single_socket set to true too, so they can’t have two different sessions right?

The players join the queue join add_matchmaker_sync on Godot, after which I process the hook and add them to the queue. My interval is 10s and you can see the timestamps are exactly 10s apart too.

It seems like the tickets aren’t getting removed because if I send a remove_matchmaker_sync request, it still works after I’m in the match.