Skip to content

Commit cbf9e16

Browse files
committed
bug: fix matchmaking bug that would never pick the last lobby other than duel (cause only 2 people are needed)
1 parent cb4f2ea commit cbf9e16

File tree

1 file changed

+41
-21
lines changed

1 file changed

+41
-21
lines changed

src/matchmaking/matchmake.service.ts

Lines changed: 41 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import { ExpectedPlayers } from "src/discord-bot/enums/ExpectedPlayers";
2424
export class MatchmakeService {
2525
public redis: Redis;
2626

27+
// TODO - fix race conditions for matchmaking across multiple regions
2728
constructor(
2829
public readonly logger: Logger,
2930
public readonly hasura: HasuraService,
@@ -124,7 +125,8 @@ export class MatchmakeService {
124125
public async matchmake(type: e_match_types_enum, region: string) {
125126
const lock = await this.aquireMatchmakeRegionLock(region);
126127
if (!lock) {
127-
return;
128+
console.warn("unable to acquire lock for region", region);
129+
return 0;
128130
}
129131

130132
// TODO - its possible, but highly unlikley we will ever runinto the issue of too many lobbies in the queue
@@ -137,12 +139,8 @@ export class MatchmakeService {
137139

138140
let lobbies = await this.processLobbyData(lobbiesData);
139141

140-
this.logger.log(
141-
`Found ${lobbies.length} lobbies in queue for ${region} ${type}`,
142-
);
143-
144142
if (lobbies.length === 0) {
145-
return;
143+
return 0;
146144
}
147145

148146
// sort lobbies by a weighted score combining rank difference and wait time
@@ -184,13 +182,13 @@ export class MatchmakeService {
184182
continue;
185183
}
186184

187-
// calculate wait time in minutes
188-
const waitTimeMinutes = Math.floor(
189-
(Date.now() - firstLobbyInGroup.joinedAt.getTime()) / (1000 * 60),
190-
);
185+
// calculate wait time in seconds
186+
const waitTimeSeconds = Math.max(10, Math.floor(
187+
(Date.now() - firstLobbyInGroup.joinedAt.getTime()) / 1000,
188+
));
191189

192-
// maximum allowed rank difference increases by 100 for each minute waited
193-
const maxRankDiff = 1000 * (waitTimeMinutes + 1);
190+
// maximum allowed rank difference increases proportionally with wait time (100 per minute)
191+
const maxRankDiff = 25 * waitTimeSeconds;
194192

195193
// check if current lobby's rank is within acceptable range
196194
if (
@@ -224,13 +222,23 @@ export class MatchmakeService {
224222
void this.releaseMatchmakeRegionLock(region);
225223
});
226224

227-
if (!results.some((result) => result === true)) {
225+
const totalPlayerNotQueued = results.reduce(
226+
(acc, result) => acc + result,
227+
0,
228+
);
229+
230+
if (totalPlayerNotQueued < ExpectedPlayers[type]) {
228231
return;
229232
}
230233

234+
this.logger.log(
235+
`${totalPlayerNotQueued} players not queued, expanding search....`,
236+
);
237+
238+
// randomize the time to prevent all regions from matchingmake at the same time
231239
setTimeout(() => {
232240
void this.matchmake(type, region);
233-
}, 5 * 1000);
241+
}, (10000 + Math.floor(Math.random() * 10000)));
234242
}
235243

236244
private async processLobbyData(
@@ -250,6 +258,7 @@ export class MatchmakeService {
250258
if (details.players.length === ExpectedPlayers[details.type]) {
251259
const lock = await this.accquireLobbyLock(details.lobbyId);
252260
if (!lock) {
261+
console.warn("unable to acquire lock for lobby", details.lobbyId);
253262
continue;
254263
}
255264

@@ -298,15 +307,19 @@ export class MatchmakeService {
298307
region: string,
299308
type: e_match_types_enum,
300309
lobbies: Array<MatchmakingLobby>,
301-
): Promise<boolean> {
310+
): Promise<number> {
302311
const requiredPlayers = ExpectedPlayers[type];
303312
const totalPlayers = lobbies.reduce(
304313
(acc, lobby) => acc + lobby.players.length,
305314
0,
306315
);
307316

308-
if (lobbies.length === 0 || totalPlayers < requiredPlayers) {
309-
return false;
317+
if (lobbies.length === 0) {
318+
return 0;
319+
}
320+
321+
if (totalPlayers < requiredPlayers) {
322+
return totalPlayers;
310323
}
311324

312325
// try to make as many valid matches as possible
@@ -333,6 +346,7 @@ export class MatchmakeService {
333346
if (team1.players.length + lobby.players.length <= playersPerTeam) {
334347
const lock = await this.accquireLobbyLock(lobby.lobbyId);
335348
if (!lock) {
349+
console.warn("unable to acquire lock for lobby", lobby.lobbyId);
336350
continue;
337351
}
338352

@@ -345,8 +359,7 @@ export class MatchmakeService {
345359
team1.lobbies.length;
346360
lobbiesAdded.push(lobbyIndex);
347361
} else if (
348-
team2.players.length + lobby.players.length <=
349-
playersPerTeam
362+
team2.players.length + lobby.players.length <= playersPerTeam
350363
) {
351364
const lock = await this.accquireLobbyLock(lobby.lobbyId);
352365
if (!lock) {
@@ -359,7 +372,6 @@ export class MatchmakeService {
359372
team2.avgRank =
360373
(team2.avgRank * (team2.lobbies.length - 1) + lobby.avgRank) /
361374
team2.lobbies.length;
362-
lobbies.splice(lobbies.indexOf(lobby), 1);
363375
lobbiesAdded.push(lobbyIndex);
364376
}
365377
}
@@ -368,6 +380,7 @@ export class MatchmakeService {
368380
lobbies.splice(lobbyIndex, 1);
369381
}
370382

383+
let totalPlayerNotQueued = 0;
371384
// check if we have valid teams for this match
372385
if (
373386
team1.players.length === playersPerTeam &&
@@ -382,6 +395,8 @@ export class MatchmakeService {
382395
team1,
383396
team2,
384397
});
398+
} else {
399+
totalPlayerNotQueued = team1.players.length + team2.players.length;
385400
}
386401

387402
// only try to re-matchmake lobbies that we were able to accuire a lock for
@@ -394,6 +409,8 @@ export class MatchmakeService {
394409
}
395410
await this.createMatches(region, type, lobbiesToMatch);
396411
}
412+
413+
return totalPlayerNotQueued;
397414
}
398415

399416
private async aquireMatchmakeRegionLock(region: string): Promise<boolean> {
@@ -613,7 +630,10 @@ export class MatchmakeService {
613630
await this.sendRegionStats();
614631

615632
if (shouldMatchmake) {
616-
void this.matchmake(type, region);
633+
// randomize the time to prevent all regions from matchingmake at the same time
634+
setTimeout(() => {
635+
void this.matchmake(type, region);
636+
}, (Math.floor(Math.random() * 10000)));
617637
}
618638
}
619639

0 commit comments

Comments
 (0)