@@ -43,10 +43,23 @@ async function addRoom(room: Room) {
43
43
bus . emit ( "load" , room . name ) ;
44
44
}
45
45
46
+ let updaterInterval : NodeJS . Timer | null = null ;
46
47
export async function start ( ) {
47
48
log . info ( "Starting room manager" ) ;
48
49
49
- setInterval ( update , 1000 ) ;
50
+ updaterInterval = setInterval ( update , 1000 ) ;
51
+ process . on ( "SIGINT" , shutdown ) ;
52
+ process . on ( "SIGTERM" , shutdown ) ;
53
+ }
54
+
55
+ async function shutdown ( ) {
56
+ log . info ( "Shutting down room manager" ) ;
57
+ if ( updaterInterval ) {
58
+ clearInterval ( updaterInterval ) ;
59
+ updaterInterval = null ;
60
+ }
61
+ await Promise . all ( rooms . map ( room => unloadRoom ( room . name , { preserveRedis : true } ) ) ) ;
62
+ process . exit ( 0 ) ;
50
63
}
51
64
52
65
export function redisStateToState ( state : RoomStateFromRedis ) : RoomState {
@@ -151,23 +164,36 @@ export async function getRoom(
151
164
return ok ( room ) ;
152
165
}
153
166
154
- export async function unloadRoom ( roomName : string ) : Promise < void > {
167
+ export async function unloadRoom (
168
+ room : string | Room ,
169
+ options : Partial < { preserveRedis : boolean } > = { }
170
+ ) : Promise < void > {
171
+ const opts = _ . defaults ( options , {
172
+ preserveRedis : false ,
173
+ } ) ;
174
+
155
175
let idx = - 1 ;
156
- for ( let i = 0 ; i < rooms . length ; i ++ ) {
157
- if ( rooms [ i ] . name . toLowerCase ( ) === roomName . toLowerCase ( ) ) {
158
- idx = i ;
159
- break ;
176
+ if ( typeof room === "string" ) {
177
+ for ( let i = 0 ; i < rooms . length ; i ++ ) {
178
+ if ( rooms [ i ] . name . toLowerCase ( ) === room . toLowerCase ( ) ) {
179
+ idx = i ;
180
+ break ;
181
+ }
160
182
}
183
+ if ( idx < 0 ) {
184
+ throw new RoomNotFoundException ( room ) ;
185
+ }
186
+ room = rooms [ idx ] ;
161
187
}
162
- if ( idx >= 0 ) {
163
- log . info ( `Unloading room: ${ roomName } ` ) ;
164
- await rooms [ idx ] . onBeforeUnload ( ) ;
165
- } else {
166
- throw new RoomNotFoundException ( roomName ) ;
167
- }
188
+ const roomName = room . name ;
189
+ log . info ( `Unloading room: ${ roomName } ` ) ;
190
+ await room . onBeforeUnload ( ) ;
191
+ idx = rooms [ idx ] . name === room . name ? idx : rooms . indexOf ( room ) ; // because the index may have changed across await boundaries
168
192
rooms . splice ( idx , 1 ) ;
169
- await redisClient . del ( `room:${ roomName } ` ) ;
170
- await redisClient . del ( `room-sync:${ roomName } ` ) ;
193
+ if ( ! opts . preserveRedis ) {
194
+ await redisClient . del ( `room:${ roomName } ` ) ;
195
+ await redisClient . del ( `room-sync:${ roomName } ` ) ;
196
+ }
171
197
bus . emit ( "unload" , roomName ) ;
172
198
}
173
199
@@ -184,7 +210,7 @@ export function clearRooms(): void {
184
210
/** Unload all rooms off of this node. Intended to only be used in tests. */
185
211
export async function unloadAllRooms ( ) : Promise < void > {
186
212
const names = rooms . map ( r => r . name ) ;
187
- await Promise . all ( names . map ( unloadRoom ) ) ;
213
+ await Promise . all ( names . map ( name => unloadRoom ( name ) ) ) ;
188
214
}
189
215
190
216
export function publish ( roomName : string , msg : ServerMessage ) {
0 commit comments