@@ -701,6 +701,82 @@ describe("MatchmakeService", () => {
701701 } ) ;
702702 } ) ;
703703
704+ describe ( "createMatches with multi-region lobbies" , ( ) => {
705+ it ( "should skip lobbies that fail to claim (already claimed by another region)" , async ( ) => {
706+ const region = "us-east" ;
707+ const type : e_match_types_enum = "Competitive" ;
708+
709+ const lobbies : MatchmakingLobby [ ] = [
710+ {
711+ lobbyId : "lobby-1" ,
712+ type,
713+ regions : [ region , "eu-west" ] ,
714+ players : Array . from ( { length : 5 } , ( _ , i ) => ( {
715+ steam_id : `steam-${ i + 1 } ` ,
716+ rank : 1000 ,
717+ } ) ) ,
718+ avgRank : 1000 ,
719+ joinedAt : new Date ( ) ,
720+ regionPositions : { } ,
721+ } ,
722+ {
723+ lobbyId : "lobby-2" ,
724+ type,
725+ regions : [ region ] ,
726+ players : Array . from ( { length : 5 } , ( _ , i ) => ( {
727+ steam_id : `steam-${ i + 6 } ` ,
728+ rank : 1050 ,
729+ } ) ) ,
730+ avgRank : 1050 ,
731+ joinedAt : new Date ( ) ,
732+ regionPositions : { } ,
733+ } ,
734+ {
735+ lobbyId : "lobby-3" ,
736+ type,
737+ regions : [ region ] ,
738+ players : Array . from ( { length : 5 } , ( _ , i ) => ( {
739+ steam_id : `steam-${ i + 11 } ` ,
740+ rank : 1100 ,
741+ } ) ) ,
742+ avgRank : 1100 ,
743+ joinedAt : new Date ( ) ,
744+ regionPositions : { } ,
745+ } ,
746+ ] ;
747+
748+ mockMatchmakingLobbyService . getLobbyDetails . mockImplementation (
749+ async ( lobbyId : string ) => {
750+ return lobbies . find ( ( l ) => l . lobbyId === lobbyId ) || null ;
751+ } ,
752+ ) ;
753+
754+ // lobby-1 fails to claim (another region got it), lobby-2 and lobby-3 succeed
755+ mockRedis . eval
756+ . mockResolvedValueOnce ( 0 ) // lobby-1: already claimed
757+ . mockResolvedValueOnce ( 1 ) // lobby-2: claimed
758+ . mockResolvedValueOnce ( 1 ) ; // lobby-3: claimed
759+
760+ const createMatchConfirmationSpy = jest
761+ . spyOn ( service as any , "createMatchConfirmation" )
762+ . mockResolvedValue ( undefined ) ;
763+
764+ await ( service as any ) . createMatches ( region , type , lobbies ) ;
765+
766+ // Should still create a match from lobby-2 + lobby-3
767+ expect ( createMatchConfirmationSpy ) . toHaveBeenCalledTimes ( 1 ) ;
768+ const callArgs = createMatchConfirmationSpy . mock . calls [ 0 ] ;
769+ const { team1, team2 } = callArgs [ 2 ] ;
770+ expect ( team1 . players . length + team2 . players . length ) . toBe ( 10 ) ;
771+
772+ // lobby-1 should NOT be in either team
773+ const allLobbies = [ ...team1 . lobbies , ...team2 . lobbies ] ;
774+ expect ( allLobbies ) . not . toContain ( "lobby-1" ) ;
775+
776+ createMatchConfirmationSpy . mockRestore ( ) ;
777+ } ) ;
778+ } ) ;
779+
704780 describe ( "releaseLobbyAndRequeue" , ( ) => {
705781 it ( "should release the lock and re-add lobby to all regional queues" , async ( ) => {
706782 const lobby : MatchmakingLobby = {
0 commit comments