@@ -782,3 +782,151 @@ func TestRedisStateStorage_GetRunningMatchesCount(t *testing.T) {
782782 require .Equal (t , 6 , count )
783783 })
784784}
785+
786+ func TestRedisStateStorage_AllocateRoom (t * testing.T ) {
787+ ctx := context .Background ()
788+
789+ t .Run ("successfully allocates a ready room" , func (t * testing.T ) {
790+ client := test .GetRedisConnection (t , redisAddress )
791+ storage := NewRedisStateStorage (client )
792+
793+ room := & game_room.GameRoom {
794+ ID : "room-1" ,
795+ SchedulerID : "game" ,
796+ Version : "1.0" ,
797+ Status : game_room .GameStatusReady ,
798+ LastPingAt : time .Unix (1 , 0 ),
799+ Metadata : map [string ]interface {}{"host" : "localhost" },
800+ }
801+
802+ require .NoError (t , storage .CreateRoom (ctx , room ))
803+
804+ allocatedRoomID , err := storage .AllocateRoom (ctx , "game" )
805+ require .NoError (t , err )
806+ require .Equal (t , "room-1" , allocatedRoomID )
807+
808+ // Verify the room status was changed to allocated
809+ updatedRoom , err := storage .GetRoom (ctx , "game" , "room-1" )
810+ require .NoError (t , err )
811+ require .Equal (t , game_room .GameStatusAllocated , updatedRoom .Status )
812+
813+ // Verify the AllocatedAt timestamp was set
814+ require .NotNil (t , updatedRoom .AllocatedAt , "AllocatedAt should be set" )
815+ require .True (t , time .Since (* updatedRoom .AllocatedAt ) < 5 * time .Second , "AllocatedAt should be recent" )
816+ })
817+
818+ t .Run ("returns error when no ready rooms available" , func (t * testing.T ) {
819+ client := test .GetRedisConnection (t , redisAddress )
820+ storage := NewRedisStateStorage (client )
821+
822+ room := & game_room.GameRoom {
823+ ID : "room-1" ,
824+ SchedulerID : "game" ,
825+ Version : "1.0" ,
826+ Status : game_room .GameStatusOccupied ,
827+ LastPingAt : time .Unix (1 , 0 ),
828+ Metadata : map [string ]interface {}{"host" : "localhost" },
829+ }
830+
831+ require .NoError (t , storage .CreateRoom (ctx , room ))
832+
833+ allocatedRoomID , err := storage .AllocateRoom (ctx , "game" )
834+ require .Error (t , err )
835+ require .Equal (t , "" , allocatedRoomID )
836+ require .Contains (t , err .Error (), "no ready rooms available" )
837+ })
838+
839+ t .Run ("returns error when scheduler has no rooms" , func (t * testing.T ) {
840+ client := test .GetRedisConnection (t , redisAddress )
841+ storage := NewRedisStateStorage (client )
842+
843+ allocatedRoomID , err := storage .AllocateRoom (ctx , "nonexistent" )
844+ require .Error (t , err )
845+ require .Equal (t , "" , allocatedRoomID )
846+ require .Contains (t , err .Error (), "no ready rooms available" )
847+ })
848+
849+ t .Run ("allocates only one room when multiple ready rooms exist" , func (t * testing.T ) {
850+ client := test .GetRedisConnection (t , redisAddress )
851+ storage := NewRedisStateStorage (client )
852+
853+ rooms := []* game_room.GameRoom {
854+ {
855+ ID : "room-1" ,
856+ SchedulerID : "game" ,
857+ Version : "1.0" ,
858+ Status : game_room .GameStatusReady ,
859+ LastPingAt : time .Unix (1 , 0 ),
860+ Metadata : map [string ]interface {}{"host" : "localhost" },
861+ },
862+ {
863+ ID : "room-2" ,
864+ SchedulerID : "game" ,
865+ Version : "1.0" ,
866+ Status : game_room .GameStatusReady ,
867+ LastPingAt : time .Unix (2 , 0 ),
868+ Metadata : map [string ]interface {}{"host" : "localhost" },
869+ },
870+ }
871+
872+ for _ , room := range rooms {
873+ require .NoError (t , storage .CreateRoom (ctx , room ))
874+ }
875+
876+ allocatedRoomID , err := storage .AllocateRoom (ctx , "game" )
877+ require .NoError (t , err )
878+ require .NotEmpty (t , allocatedRoomID )
879+ require .Contains (t , []string {"room-1" , "room-2" }, allocatedRoomID )
880+
881+ // Verify only the allocated room was changed to allocated
882+ readyRooms , err := storage .GetRoomIDsByStatus (ctx , "game" , game_room .GameStatusReady )
883+ require .NoError (t , err )
884+ require .Len (t , readyRooms , 1 )
885+
886+ allocatedRooms , err := storage .GetRoomIDsByStatus (ctx , "game" , game_room .GameStatusAllocated )
887+ require .NoError (t , err )
888+ require .Len (t , allocatedRooms , 1 )
889+ require .Equal (t , allocatedRoomID , allocatedRooms [0 ])
890+ })
891+
892+ t .Run ("ignores non-ready rooms" , func (t * testing.T ) {
893+ client := test .GetRedisConnection (t , redisAddress )
894+ storage := NewRedisStateStorage (client )
895+
896+ rooms := []* game_room.GameRoom {
897+ {
898+ ID : "room-pending" ,
899+ SchedulerID : "game" ,
900+ Version : "1.0" ,
901+ Status : game_room .GameStatusPending ,
902+ LastPingAt : time .Unix (1 , 0 ),
903+ Metadata : map [string ]interface {}{"host" : "localhost" },
904+ },
905+ {
906+ ID : "room-occupied" ,
907+ SchedulerID : "game" ,
908+ Version : "1.0" ,
909+ Status : game_room .GameStatusOccupied ,
910+ LastPingAt : time .Unix (2 , 0 ),
911+ Metadata : map [string ]interface {}{"host" : "localhost" },
912+ },
913+ {
914+ ID : "room-terminating" ,
915+ SchedulerID : "game" ,
916+ Version : "1.0" ,
917+ Status : game_room .GameStatusTerminating ,
918+ LastPingAt : time .Unix (3 , 0 ),
919+ Metadata : map [string ]interface {}{"host" : "localhost" },
920+ },
921+ }
922+
923+ for _ , room := range rooms {
924+ require .NoError (t , storage .CreateRoom (ctx , room ))
925+ }
926+
927+ allocatedRoomID , err := storage .AllocateRoom (ctx , "game" )
928+ require .Error (t , err )
929+ require .Equal (t , "" , allocatedRoomID )
930+ require .Contains (t , err .Error (), "no ready rooms available" )
931+ })
932+ }
0 commit comments