1
1
import { CommandHandler , EventBus , ICommandHandler , QueryBus } from '@nestjs/cqrs' ;
2
2
import { Inject , Logger } from '@nestjs/common' ;
3
3
import { FindGameServerCommand } from 'gameserver/command/FindGameServer/find-game-server.command' ;
4
- import { GameSessionCreatedEvent } from 'gateway/events/game-session-created.event' ;
5
4
import { GameServerSessionRepository } from 'gameserver/repository/game-server-session.repository' ;
6
5
import { GameServerSessionEntity } from 'gameserver/model/game-server-session.entity' ;
7
6
import { InjectRepository } from '@nestjs/typeorm' ;
8
7
import { Repository } from 'typeorm' ;
9
- import { GameServerEntity } from 'gameserver/model/game-server.entity' ;
10
8
import { ClientProxy } from '@nestjs/microservices' ;
11
9
import {
12
10
FullMatchPlayer ,
13
11
GSMatchInfo ,
14
12
LaunchGameServerCommand ,
15
13
} from 'gateway/commands/LaunchGameServer/launch-game-server.command' ;
16
- import { LaunchGameServerResponse } from 'gateway/commands/LaunchGameServer/launch-game-server.response' ;
17
- import { timeout } from 'rxjs/operators' ;
18
- import { ServerNotRespondingEvent } from 'gameserver/event/server-not-responding.event' ;
19
- import { MatchCancelledEvent } from 'gateway/events/match-cancelled.event' ;
20
- import { inspect } from 'util' ;
21
- import { Subject } from 'rxjs' ;
22
- import { asyncMap } from 'rxjs-async-map' ;
23
- import { KillServerRequestedEvent } from 'gateway/events/gs/kill-server-requested.event' ;
24
- import { MatchStartedEvent } from 'gateway/events/match-started.event' ;
25
- import { GameServerInfo } from 'gateway/shared-types/game-server-info' ;
26
- import { MatchInfo } from 'gateway/events/room-ready.event' ;
27
14
import { GetUserInfoQuery } from 'gateway/queries/GetUserInfo/get-user-info.query' ;
28
15
import { GetUserInfoQueryResult } from 'gateway/queries/GetUserInfo/get-user-info-query.result' ;
29
16
import { MatchEntity } from 'gameserver/model/match.entity' ;
@@ -32,16 +19,14 @@ import { Dota_GameMode } from 'gateway/shared-types/dota-game-mode';
32
19
import { MatchmakingModeMappingEntity } from 'gameserver/model/matchmaking-mode-mapping.entity' ;
33
20
import { Dota_Map } from 'gateway/shared-types/dota-map' ;
34
21
import { GamePreparedEvent } from 'gameserver/event/game-prepared.event' ;
22
+ import { ConfigService } from '@nestjs/config' ;
35
23
36
24
@CommandHandler ( FindGameServerCommand )
37
25
export class FindGameServerHandler
38
26
implements ICommandHandler < FindGameServerCommand >
39
27
{
40
28
private readonly logger = new Logger ( FindGameServerHandler . name ) ;
41
29
42
- private pendingGamesPool : Subject < FindGameServerCommand > =
43
- new Subject < FindGameServerCommand > ( ) ;
44
-
45
30
constructor (
46
31
private readonly gsSessionRepository : GameServerSessionRepository ,
47
32
@InjectRepository ( GameServerSessionEntity )
@@ -51,16 +36,31 @@ export class FindGameServerHandler
51
36
private readonly matchEntityRepository : Repository < MatchEntity > ,
52
37
private readonly qbus : QueryBus ,
53
38
@Inject ( "QueryCore" ) private readonly redisEventQueue : ClientProxy ,
39
+ @Inject ( "RMQ" ) private readonly rmq : ClientProxy ,
40
+ private readonly config : ConfigService ,
54
41
@InjectRepository ( MatchmakingModeMappingEntity )
55
42
private readonly matchmakingModeMappingEntityRepository : Repository < MatchmakingModeMappingEntity > ,
56
43
) {
57
- this . pendingGamesPool
58
- . pipe ( asyncMap ( ( cmd ) => this . findServer ( cmd ) , 1 ) )
59
- . subscribe ( ) ;
44
+
60
45
}
61
46
62
47
async execute ( command : FindGameServerCommand ) {
63
- this . pendingGamesPool . next ( command ) ;
48
+ const gsInfo = await this . extendMatchInfo ( command . info ) ;
49
+
50
+ const m = new MatchEntity ( ) ;
51
+ m . server = MatchEntity . NOT_DECIDED_SERVER ;
52
+ m . mode = command . info . mode ;
53
+ m . started = false ;
54
+ m . finished = false ;
55
+ m . matchInfoJson = {
56
+ ...gsInfo ,
57
+ } ;
58
+
59
+ await this . matchEntityRepository . save ( m ) ;
60
+
61
+ this . logger . log ( "Created match stub" ) ;
62
+
63
+ await this . submitQueueTask ( m . id , gsInfo ) ;
64
64
}
65
65
66
66
private async getMapForMatchMode ( mode : MatchmakingMode ) : Promise < Dota_Map > {
@@ -126,113 +126,11 @@ export class FindGameServerHandler
126
126
) ;
127
127
}
128
128
129
- private async findServer ( command : FindGameServerCommand ) {
130
- const freeServerPool = await this . gsSessionRepository . getAllFree (
131
- command . info . version ,
132
- ) ;
133
-
134
- const gsInfo = await this . extendMatchInfo ( command . info ) ;
135
-
136
- console . log ( "FindServer called, pool" , freeServerPool ) ;
137
-
138
- const m = new MatchEntity ( ) ;
139
- m . server = MatchEntity . NOT_DECIDED_SERVER ;
140
- m . mode = command . info . mode ;
141
- m . started = false ;
142
- m . finished = false ;
143
- m . matchInfoJson = {
144
- ...gsInfo ,
145
- } ;
146
-
147
- await this . matchEntityRepository . save ( m ) ;
148
-
149
- let i = 0 ;
150
- let foundServer : GameServerEntity | undefined ;
151
-
152
- console . log ( "Free pool:" , freeServerPool . length ) ;
153
- while ( i < freeServerPool . length ) {
154
- const candidate = freeServerPool [ i ] ;
155
- const stackUrl = candidate . url ;
156
- try {
157
- const cmd = new LaunchGameServerCommand ( candidate . url , m . id , gsInfo ) ;
158
- console . log ( JSON . stringify ( cmd , null , 2 ) ) ;
159
- const req = await this . redisEventQueue
160
- . send <
161
- LaunchGameServerResponse ,
162
- LaunchGameServerCommand
163
- > ( LaunchGameServerCommand . name , cmd )
164
- . pipe ( timeout ( 15000 ) )
165
- . toPromise ( ) ;
166
-
167
- // we got req, now need to deci
168
- if ( req . successful ) {
169
- // server launcher
170
- foundServer = candidate ;
171
- break ;
172
- } else {
173
- console . log ( req ) ;
174
- // server not launched for some reason
175
- // i guess we skip? just try next server
176
- }
177
- } catch ( e ) {
178
- console . log ( "Sadkek?" , e ) ;
179
- console . error ( e . stack ) ;
180
- // timeout means server is DEAD
181
- this . ebus . publish ( new ServerNotRespondingEvent ( stackUrl ) ) ;
182
- // just to make sure server is dead
183
- this . ebus . publish ( new KillServerRequestedEvent ( stackUrl ) ) ;
184
- }
185
-
186
- i ++ ;
187
- }
188
-
189
- console . log ( "So: " , inspect ( foundServer ) ) ;
190
-
191
- if ( foundServer ) {
192
- m . server = foundServer . url ;
193
- await this . matchEntityRepository . save ( m ) ;
194
- } else {
195
- // cancel match : no servers free :sadkek:
196
- this . ebus . publish (
197
- new MatchCancelledEvent (
198
- m . id ,
199
- new MatchInfo (
200
- command . info . mode ,
201
- command . info . roomId ,
202
- command . info . players ,
203
- 0 ,
204
- command . info . version ,
205
- ) ,
206
- ) ,
207
- ) ;
208
- return ;
209
- }
210
- // ok here we launch server
211
-
212
- const session = new GameServerSessionEntity ( ) ;
213
- session . url = foundServer . url ;
214
-
215
- session . matchId = m . id ;
216
- session . matchInfoJson = {
217
- ...gsInfo ,
218
- } ;
219
-
220
- await this . gameServerSessionModelRepository . save ( session ) ;
221
-
222
- this . ebus . publish (
223
- new GameSessionCreatedEvent (
224
- session . url ,
225
- session . matchId ,
226
- session . matchInfoJson ,
227
- ) ,
228
- ) ;
229
-
230
- this . ebus . publish (
231
- new MatchStartedEvent (
232
- session . matchId ,
233
- session . matchInfoJson ,
234
- new GameServerInfo ( session . url ) ,
235
- ) ,
129
+ private async submitQueueTask ( matchId : number , info : GSMatchInfo ) {
130
+ this . rmq . emit (
131
+ LaunchGameServerCommand . name ,
132
+ new LaunchGameServerCommand ( matchId , info ) ,
236
133
) ;
134
+ this . logger . log ( "Submitted start server command to queue" ) ;
237
135
}
238
136
}
0 commit comments