@@ -24,6 +24,7 @@ import { ExpectedPlayers } from "src/discord-bot/enums/ExpectedPlayers";
2424export 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