@colyseus/core 0.16.0-preview.9 → 0.16.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -5
- package/build/Debug.js +6 -2
- package/build/Debug.js.map +2 -2
- package/build/Debug.mjs +11 -10
- package/build/Debug.mjs.map +2 -2
- package/build/IPC.d.ts +1 -1
- package/build/IPC.js +3 -3
- package/build/IPC.js.map +2 -2
- package/build/IPC.mjs +4 -3
- package/build/IPC.mjs.map +2 -2
- package/build/Logger.mjs +4 -3
- package/build/Logger.mjs.map +1 -1
- package/build/MatchMaker.d.ts +35 -30
- package/build/MatchMaker.js +150 -100
- package/build/MatchMaker.js.map +2 -2
- package/build/MatchMaker.mjs +154 -107
- package/build/MatchMaker.mjs.map +2 -2
- package/build/Protocol.d.ts +3 -4
- package/build/Protocol.js +33 -19
- package/build/Protocol.js.map +2 -2
- package/build/Protocol.mjs +36 -21
- package/build/Protocol.mjs.map +2 -2
- package/build/Room.d.ts +64 -40
- package/build/Room.js +408 -151
- package/build/Room.js.map +2 -2
- package/build/Room.mjs +412 -158
- package/build/Room.mjs.map +2 -2
- package/build/Server.d.ts +8 -7
- package/build/Server.js +51 -18
- package/build/Server.js.map +2 -2
- package/build/Server.mjs +51 -21
- package/build/Server.mjs.map +3 -3
- package/build/Stats.d.ts +2 -0
- package/build/Stats.js +38 -3
- package/build/Stats.js.map +2 -2
- package/build/Stats.mjs +30 -6
- package/build/Stats.mjs.map +2 -2
- package/build/Transport.d.ts +8 -7
- package/build/Transport.js +1 -1
- package/build/Transport.js.map +2 -2
- package/build/Transport.mjs +6 -5
- package/build/Transport.mjs.map +2 -2
- package/build/discovery/index.d.ts +1 -1
- package/build/discovery/index.js.map +2 -2
- package/build/discovery/index.mjs +3 -2
- package/build/discovery/index.mjs.map +2 -2
- package/build/errors/RoomExceptions.d.ts +39 -0
- package/build/errors/RoomExceptions.js +100 -0
- package/build/errors/RoomExceptions.js.map +7 -0
- package/build/errors/RoomExceptions.mjs +71 -0
- package/build/errors/RoomExceptions.mjs.map +7 -0
- package/build/errors/SeatReservationError.mjs +3 -2
- package/build/errors/SeatReservationError.mjs.map +1 -1
- package/build/errors/ServerError.js +1 -1
- package/build/errors/ServerError.js.map +1 -1
- package/build/errors/ServerError.mjs +5 -4
- package/build/errors/ServerError.mjs.map +2 -2
- package/build/index.d.ts +21 -19
- package/build/index.js +45 -20
- package/build/index.js.map +2 -2
- package/build/index.mjs +39 -19
- package/build/index.mjs.map +2 -2
- package/build/matchmaker/Lobby.d.ts +3 -3
- package/build/matchmaker/Lobby.js +6 -3
- package/build/matchmaker/Lobby.js.map +2 -2
- package/build/matchmaker/Lobby.mjs +4 -4
- package/build/matchmaker/Lobby.mjs.map +2 -2
- package/build/matchmaker/RegisteredHandler.d.ts +6 -7
- package/build/matchmaker/RegisteredHandler.js +7 -10
- package/build/matchmaker/RegisteredHandler.js.map +2 -2
- package/build/matchmaker/RegisteredHandler.mjs +11 -13
- package/build/matchmaker/RegisteredHandler.mjs.map +2 -2
- package/build/matchmaker/controller.d.ts +4 -5
- package/build/matchmaker/controller.js +22 -15
- package/build/matchmaker/controller.js.map +2 -2
- package/build/matchmaker/controller.mjs +19 -13
- package/build/matchmaker/controller.mjs.map +2 -2
- package/build/matchmaker/driver/api.d.ts +104 -0
- package/build/matchmaker/driver/api.js +29 -0
- package/build/matchmaker/driver/api.js.map +7 -0
- package/build/matchmaker/driver/api.mjs +7 -0
- package/build/matchmaker/driver/api.mjs.map +7 -0
- package/build/matchmaker/driver/index.d.ts +2 -2
- package/build/matchmaker/driver/index.js +2 -2
- package/build/matchmaker/driver/index.js.map +2 -2
- package/build/matchmaker/driver/index.mjs +5 -4
- package/build/matchmaker/driver/index.mjs.map +2 -2
- package/build/matchmaker/driver/local/LocalDriver.d.ts +13 -0
- package/build/matchmaker/driver/local/LocalDriver.js +65 -0
- package/build/matchmaker/driver/local/LocalDriver.js.map +7 -0
- package/build/matchmaker/driver/local/LocalDriver.mjs +43 -0
- package/build/matchmaker/driver/local/LocalDriver.mjs.map +7 -0
- package/build/matchmaker/driver/local/Query.d.ts +9 -0
- package/build/matchmaker/driver/local/Query.js +78 -0
- package/build/matchmaker/driver/local/Query.js.map +7 -0
- package/build/matchmaker/driver/local/Query.mjs +56 -0
- package/build/matchmaker/driver/local/Query.mjs.map +7 -0
- package/build/matchmaker/driver/local/RoomData.d.ts +19 -0
- package/build/matchmaker/driver/local/RoomData.js +79 -0
- package/build/matchmaker/driver/local/RoomData.js.map +7 -0
- package/build/matchmaker/driver/local/RoomData.mjs +57 -0
- package/build/matchmaker/driver/local/RoomData.mjs.map +7 -0
- package/build/presence/LocalPresence.d.ts +10 -6
- package/build/presence/LocalPresence.js +85 -24
- package/build/presence/LocalPresence.js.map +3 -3
- package/build/presence/LocalPresence.mjs +85 -27
- package/build/presence/LocalPresence.mjs.map +3 -3
- package/build/presence/Presence.d.ts +38 -2
- package/build/presence/Presence.js.map +1 -1
- package/build/rooms/LobbyRoom.d.ts +6 -6
- package/build/rooms/LobbyRoom.js +8 -3
- package/build/rooms/LobbyRoom.js.map +2 -2
- package/build/rooms/LobbyRoom.mjs +7 -5
- package/build/rooms/LobbyRoom.mjs.map +2 -2
- package/build/rooms/RelayRoom.d.ts +3 -3
- package/build/rooms/RelayRoom.js +3 -1
- package/build/rooms/RelayRoom.js.map +2 -2
- package/build/rooms/RelayRoom.mjs +10 -7
- package/build/rooms/RelayRoom.mjs.map +2 -2
- package/build/serializer/NoneSerializer.d.ts +2 -2
- package/build/serializer/NoneSerializer.js.map +1 -1
- package/build/serializer/NoneSerializer.mjs +3 -2
- package/build/serializer/NoneSerializer.mjs.map +2 -2
- package/build/serializer/SchemaSerializer.d.ts +16 -15
- package/build/serializer/SchemaSerializer.js +12 -10
- package/build/serializer/SchemaSerializer.js.map +2 -2
- package/build/serializer/SchemaSerializer.mjs +16 -13
- package/build/serializer/SchemaSerializer.mjs.map +2 -2
- package/build/serializer/SchemaSerializerDebug.d.ts +7 -0
- package/build/serializer/SchemaSerializerDebug.js +0 -0
- package/build/serializer/SchemaSerializerDebug.js.map +7 -0
- package/build/serializer/SchemaSerializerDebug.mjs +0 -0
- package/build/serializer/SchemaSerializerDebug.mjs.map +7 -0
- package/build/serializer/Serializer.d.ts +1 -2
- package/build/serializer/Serializer.js.map +1 -1
- package/build/utils/DevMode.d.ts +2 -2
- package/build/utils/DevMode.js +8 -4
- package/build/utils/DevMode.js.map +2 -2
- package/build/utils/DevMode.mjs +7 -6
- package/build/utils/DevMode.mjs.map +2 -2
- package/build/utils/Utils.d.ts +8 -3
- package/build/utils/Utils.js +41 -17
- package/build/utils/Utils.js.map +2 -2
- package/build/utils/Utils.mjs +40 -21
- package/build/utils/Utils.mjs.map +2 -2
- package/package.json +17 -6
package/build/MatchMaker.mjs
CHANGED
|
@@ -1,39 +1,45 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import
|
|
13
|
-
import
|
|
14
|
-
import
|
|
15
|
-
import
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
1
|
+
// packages/core/src/MatchMaker.ts
|
|
2
|
+
import { EventEmitter } from "events";
|
|
3
|
+
import { ErrorCode, Protocol } from "./Protocol.mjs";
|
|
4
|
+
import { requestFromIPC, subscribeIPC } from "./IPC.mjs";
|
|
5
|
+
import { Deferred, generateId, merge, retry, MAX_CONCURRENT_CREATE_ROOM_WAIT_TIME, REMOTE_ROOM_SHORT_TIMEOUT } from "./utils/Utils.mjs";
|
|
6
|
+
import { isDevMode, cacheRoomHistory, getPreviousProcessId, getRoomRestoreListKey, reloadFromCache } from "./utils/DevMode.mjs";
|
|
7
|
+
import { RegisteredHandler } from "./matchmaker/RegisteredHandler.mjs";
|
|
8
|
+
import { Room, RoomInternalState } from "./Room.mjs";
|
|
9
|
+
import { LocalPresence } from "./presence/LocalPresence.mjs";
|
|
10
|
+
import { debugAndPrintError, debugMatchMaking } from "./Debug.mjs";
|
|
11
|
+
import { SeatReservationError } from "./errors/SeatReservationError.mjs";
|
|
12
|
+
import { ServerError } from "./errors/ServerError.mjs";
|
|
13
|
+
import { LocalDriver } from "./matchmaker/driver/local/LocalDriver.mjs";
|
|
14
|
+
import controller from "./matchmaker/controller.mjs";
|
|
15
|
+
import * as stats from "./Stats.mjs";
|
|
16
|
+
import { logger } from "./Logger.mjs";
|
|
17
|
+
import { getHostname } from "./discovery/index.mjs";
|
|
18
|
+
import { getLockId } from "./matchmaker/driver/api.mjs";
|
|
19
|
+
var handlers = {};
|
|
20
|
+
var rooms = {};
|
|
21
|
+
var events = new EventEmitter();
|
|
22
|
+
var publicAddress;
|
|
23
|
+
var processId;
|
|
24
|
+
var presence;
|
|
25
|
+
var driver;
|
|
26
|
+
var selectProcessIdToCreateRoom;
|
|
27
|
+
var enableHealthChecks = true;
|
|
28
|
+
function setHealthChecksEnabled(value) {
|
|
29
|
+
enableHealthChecks = value;
|
|
30
|
+
}
|
|
31
|
+
var onReady = new Deferred();
|
|
25
32
|
var MatchMakerState = /* @__PURE__ */ ((MatchMakerState2) => {
|
|
26
33
|
MatchMakerState2[MatchMakerState2["INITIALIZING"] = 0] = "INITIALIZING";
|
|
27
34
|
MatchMakerState2[MatchMakerState2["READY"] = 1] = "READY";
|
|
28
35
|
MatchMakerState2[MatchMakerState2["SHUTTING_DOWN"] = 2] = "SHUTTING_DOWN";
|
|
29
36
|
return MatchMakerState2;
|
|
30
37
|
})(MatchMakerState || {});
|
|
31
|
-
|
|
38
|
+
var state;
|
|
32
39
|
async function setup(_presence, _driver, _publicAddress, _selectProcessIdToCreateRoom) {
|
|
33
40
|
if (onReady === void 0) {
|
|
34
41
|
onReady = new Deferred();
|
|
35
42
|
}
|
|
36
|
-
isGracefullyShuttingDown = false;
|
|
37
43
|
state = 0 /* INITIALIZING */;
|
|
38
44
|
presence = _presence || new LocalPresence();
|
|
39
45
|
driver = _driver || new LocalDriver();
|
|
@@ -59,25 +65,44 @@ async function accept() {
|
|
|
59
65
|
return handleCreateRoom.apply(void 0, args);
|
|
60
66
|
}
|
|
61
67
|
});
|
|
62
|
-
|
|
68
|
+
if (enableHealthChecks) {
|
|
69
|
+
await healthCheckAllProcesses();
|
|
70
|
+
stats.setAutoPersistInterval();
|
|
71
|
+
}
|
|
63
72
|
state = 1 /* READY */;
|
|
64
73
|
await stats.persist();
|
|
65
74
|
if (isDevMode) {
|
|
66
75
|
await reloadFromCache();
|
|
67
76
|
}
|
|
68
77
|
}
|
|
69
|
-
async function joinOrCreate(roomName, clientOptions = {},
|
|
78
|
+
async function joinOrCreate(roomName, clientOptions = {}, authContext) {
|
|
70
79
|
return await retry(async () => {
|
|
71
|
-
const authData = await callOnAuth(roomName,
|
|
80
|
+
const authData = await callOnAuth(roomName, clientOptions, authContext);
|
|
72
81
|
let room = await findOneRoomAvailable(roomName, clientOptions);
|
|
73
82
|
if (!room) {
|
|
74
|
-
|
|
83
|
+
const handler = getHandler(roomName);
|
|
84
|
+
const filterOptions = handler.getFilterOptions(clientOptions);
|
|
85
|
+
const concurrencyKey = getLockId(filterOptions);
|
|
86
|
+
await concurrentJoinOrCreateRoomLock(handler, concurrencyKey, async (roomId) => {
|
|
87
|
+
if (roomId) {
|
|
88
|
+
room = await driver.findOne({ roomId });
|
|
89
|
+
}
|
|
90
|
+
if (!room) {
|
|
91
|
+
room = await findOneRoomAvailable(roomName, clientOptions);
|
|
92
|
+
}
|
|
93
|
+
if (!room) {
|
|
94
|
+
room = await createRoom(roomName, clientOptions);
|
|
95
|
+
presence.lpush(`l:${handler.name}:${concurrencyKey}`, room.roomId);
|
|
96
|
+
presence.expire(`l:${handler.name}:${concurrencyKey}`, MAX_CONCURRENT_CREATE_ROOM_WAIT_TIME * 2);
|
|
97
|
+
}
|
|
98
|
+
return room;
|
|
99
|
+
});
|
|
75
100
|
}
|
|
76
101
|
return await reserveSeatFor(room, clientOptions, authData);
|
|
77
102
|
}, 5, [SeatReservationError]);
|
|
78
103
|
}
|
|
79
|
-
async function create(roomName, clientOptions = {},
|
|
80
|
-
const authData = await callOnAuth(roomName,
|
|
104
|
+
async function create(roomName, clientOptions = {}, authContext) {
|
|
105
|
+
const authData = await callOnAuth(roomName, clientOptions, authContext);
|
|
81
106
|
const room = await createRoom(roomName, clientOptions);
|
|
82
107
|
return reserveSeatFor(room, clientOptions, authData);
|
|
83
108
|
}
|
|
@@ -125,23 +150,21 @@ async function joinById(roomId, clientOptions = {}, authOptions) {
|
|
|
125
150
|
const authData = await callOnAuth(room.name, authOptions);
|
|
126
151
|
return reserveSeatFor(room, clientOptions, authData);
|
|
127
152
|
}
|
|
128
|
-
async function query(conditions = {}) {
|
|
129
|
-
return await driver.
|
|
130
|
-
}
|
|
131
|
-
async function findOneRoomAvailable(roomName,
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
return await roomQuery;
|
|
144
|
-
});
|
|
153
|
+
async function query(conditions = {}, sortOptions) {
|
|
154
|
+
return await driver.query(conditions, sortOptions);
|
|
155
|
+
}
|
|
156
|
+
async function findOneRoomAvailable(roomName, filterOptions, additionalSortOptions) {
|
|
157
|
+
const handler = getHandler(roomName);
|
|
158
|
+
const sortOptions = Object.assign({}, handler.sortOptions ?? {});
|
|
159
|
+
if (additionalSortOptions) {
|
|
160
|
+
Object.assign(sortOptions, additionalSortOptions);
|
|
161
|
+
}
|
|
162
|
+
return await driver.findOne({
|
|
163
|
+
locked: false,
|
|
164
|
+
name: roomName,
|
|
165
|
+
private: false,
|
|
166
|
+
...handler.getFilterOptions(filterOptions)
|
|
167
|
+
}, sortOptions);
|
|
145
168
|
}
|
|
146
169
|
async function remoteRoomCall(roomId, method, args, rejectionTimeout = REMOTE_ROOM_SHORT_TIMEOUT) {
|
|
147
170
|
const room = rooms[roomId];
|
|
@@ -163,23 +186,17 @@ async function remoteRoomCall(roomId, method, args, rejectionTimeout = REMOTE_RO
|
|
|
163
186
|
}
|
|
164
187
|
}
|
|
165
188
|
function defineRoomType(roomName, klass, defaultOptions) {
|
|
166
|
-
const registeredHandler = new RegisteredHandler(klass, defaultOptions);
|
|
189
|
+
const registeredHandler = new RegisteredHandler(roomName, klass, defaultOptions);
|
|
167
190
|
handlers[roomName] = registeredHandler;
|
|
168
191
|
if (klass.prototype["onAuth"] !== Room.prototype["onAuth"]) {
|
|
169
192
|
if (klass["onAuth"] !== Room["onAuth"]) {
|
|
170
193
|
logger.info(`\u274C "${roomName}"'s onAuth() defined at the instance level will be ignored.`);
|
|
171
194
|
}
|
|
172
195
|
}
|
|
173
|
-
if (!isDevMode) {
|
|
174
|
-
cleanupStaleRooms(roomName);
|
|
175
|
-
}
|
|
176
196
|
return registeredHandler;
|
|
177
197
|
}
|
|
178
198
|
function removeRoomType(roomName) {
|
|
179
199
|
delete handlers[roomName];
|
|
180
|
-
if (!isDevMode) {
|
|
181
|
-
cleanupStaleRooms(roomName);
|
|
182
|
-
}
|
|
183
200
|
}
|
|
184
201
|
function hasHandler(roomName) {
|
|
185
202
|
logger.warn("hasHandler() is deprecated. Use getHandler() instead.");
|
|
@@ -214,7 +231,9 @@ async function createRoom(roomName, clientOptions) {
|
|
|
214
231
|
} catch (e) {
|
|
215
232
|
if (e.message === "ipc_timeout") {
|
|
216
233
|
debugAndPrintError(`${e.message}: create room request timed out for ${roomName} on processId ${selectedProcessId}.`);
|
|
217
|
-
|
|
234
|
+
if (enableHealthChecks) {
|
|
235
|
+
await stats.excludeProcess(selectedProcessId);
|
|
236
|
+
}
|
|
218
237
|
room = await handleCreateRoom(roomName, clientOptions);
|
|
219
238
|
} else {
|
|
220
239
|
throw e;
|
|
@@ -238,9 +257,7 @@ async function handleCreateRoom(roomName, clientOptions, restoringRoomId) {
|
|
|
238
257
|
} else {
|
|
239
258
|
room.roomId = generateId();
|
|
240
259
|
}
|
|
241
|
-
|
|
242
|
-
room.setState(room.state);
|
|
243
|
-
}
|
|
260
|
+
room["__init"]();
|
|
244
261
|
room.roomName = roomName;
|
|
245
262
|
room.presence = presence;
|
|
246
263
|
const additionalListingData = handler.getFilterOptions(clientOptions);
|
|
@@ -280,13 +297,21 @@ async function handleCreateRoom(roomName, clientOptions, restoringRoomId) {
|
|
|
280
297
|
room._events.removeAllListeners("unlock");
|
|
281
298
|
room._events.removeAllListeners("visibility-change");
|
|
282
299
|
room._events.removeAllListeners("dispose");
|
|
300
|
+
if (stats.local.roomCount <= 0) {
|
|
301
|
+
events.emit("no-active-rooms");
|
|
302
|
+
}
|
|
283
303
|
});
|
|
284
304
|
await createRoomReferences(room, true);
|
|
285
|
-
|
|
305
|
+
if (state !== 2 /* SHUTTING_DOWN */) {
|
|
306
|
+
await room.listing.save();
|
|
307
|
+
}
|
|
286
308
|
handler.emit("create", room);
|
|
287
309
|
return room.listing;
|
|
288
310
|
}
|
|
289
311
|
function getRoomById(roomId) {
|
|
312
|
+
return driver.findOne({ roomId });
|
|
313
|
+
}
|
|
314
|
+
function getLocalRoomById(roomId) {
|
|
290
315
|
return rooms[roomId];
|
|
291
316
|
}
|
|
292
317
|
function disconnectAll(closeCode) {
|
|
@@ -295,24 +320,42 @@ function disconnectAll(closeCode) {
|
|
|
295
320
|
if (!rooms.hasOwnProperty(roomId)) {
|
|
296
321
|
continue;
|
|
297
322
|
}
|
|
298
|
-
|
|
299
|
-
room._events.removeAllListeners("leave");
|
|
300
|
-
promises.push(room.disconnect(closeCode));
|
|
323
|
+
promises.push(rooms[roomId].disconnect(closeCode));
|
|
301
324
|
}
|
|
302
325
|
return promises;
|
|
303
326
|
}
|
|
327
|
+
async function lockAndDisposeAll() {
|
|
328
|
+
await stats.excludeProcess(processId);
|
|
329
|
+
if (enableHealthChecks) {
|
|
330
|
+
stats.clearAutoPersistInterval();
|
|
331
|
+
}
|
|
332
|
+
const noActiveRooms = new Deferred();
|
|
333
|
+
if (stats.local.roomCount <= 0) {
|
|
334
|
+
noActiveRooms.resolve();
|
|
335
|
+
} else {
|
|
336
|
+
events.once("no-active-rooms", () => noActiveRooms.resolve());
|
|
337
|
+
}
|
|
338
|
+
for (const roomId in rooms) {
|
|
339
|
+
if (!rooms.hasOwnProperty(roomId)) {
|
|
340
|
+
continue;
|
|
341
|
+
}
|
|
342
|
+
const room = rooms[roomId];
|
|
343
|
+
room.lock();
|
|
344
|
+
room.onBeforeShutdown();
|
|
345
|
+
}
|
|
346
|
+
await noActiveRooms;
|
|
347
|
+
}
|
|
304
348
|
async function gracefullyShutdown() {
|
|
305
|
-
if (
|
|
349
|
+
if (state === 2 /* SHUTTING_DOWN */) {
|
|
306
350
|
return Promise.reject("already_shutting_down");
|
|
307
351
|
}
|
|
308
|
-
|
|
352
|
+
debugMatchMaking(`${processId} is shutting down!`);
|
|
309
353
|
state = 2 /* SHUTTING_DOWN */;
|
|
310
354
|
onReady = void 0;
|
|
311
|
-
|
|
355
|
+
await lockAndDisposeAll();
|
|
312
356
|
if (isDevMode) {
|
|
313
357
|
await cacheRoomHistory(rooms);
|
|
314
358
|
}
|
|
315
|
-
await stats.excludeProcess(processId);
|
|
316
359
|
await removeRoomsByProcessId(processId);
|
|
317
360
|
presence.unsubscribe(getProcessChannel());
|
|
318
361
|
return Promise.all(disconnectAll(
|
|
@@ -337,7 +380,7 @@ async function reserveSeatFor(room, options, authData) {
|
|
|
337
380
|
);
|
|
338
381
|
} catch (e) {
|
|
339
382
|
debugMatchMaking(e);
|
|
340
|
-
if (e.message === "ipc_timeout" && !await healthCheckProcessId(room.processId)) {
|
|
383
|
+
if (e.message === "ipc_timeout" && !(enableHealthChecks && await healthCheckProcessId(room.processId))) {
|
|
341
384
|
throw new SeatReservationError(`process ${room.processId} is not available.`);
|
|
342
385
|
} else {
|
|
343
386
|
successfulSeatReservation = false;
|
|
@@ -352,12 +395,9 @@ async function reserveSeatFor(room, options, authData) {
|
|
|
352
395
|
}
|
|
353
396
|
return response;
|
|
354
397
|
}
|
|
355
|
-
function callOnAuth(roomName,
|
|
398
|
+
function callOnAuth(roomName, clientOptions, authContext) {
|
|
356
399
|
const roomClass = getRoomClass(roomName);
|
|
357
|
-
return roomClass && roomClass["onAuth"] && roomClass["onAuth"] !== Room["onAuth"] ? roomClass["onAuth"](
|
|
358
|
-
}
|
|
359
|
-
async function cleanupStaleRooms(roomName) {
|
|
360
|
-
await presence.del(getHandlerConcurrencyKey(roomName));
|
|
400
|
+
return roomClass && roomClass["onAuth"] && roomClass["onAuth"] !== Room["onAuth"] ? roomClass["onAuth"](authContext.token, clientOptions, authContext) : void 0;
|
|
361
401
|
}
|
|
362
402
|
async function healthCheckAllProcesses() {
|
|
363
403
|
const allStats = await stats.fetchAll();
|
|
@@ -367,7 +407,7 @@ async function healthCheckAllProcesses() {
|
|
|
367
407
|
);
|
|
368
408
|
}
|
|
369
409
|
}
|
|
370
|
-
|
|
410
|
+
var _healthCheckByProcessId = {};
|
|
371
411
|
function healthCheckProcessId(processId2) {
|
|
372
412
|
if (_healthCheckByProcessId[processId2] !== void 0) {
|
|
373
413
|
return _healthCheckByProcessId[processId2];
|
|
@@ -399,13 +439,7 @@ function healthCheckProcessId(processId2) {
|
|
|
399
439
|
return _healthCheckByProcessId[processId2];
|
|
400
440
|
}
|
|
401
441
|
async function removeRoomsByProcessId(processId2) {
|
|
402
|
-
|
|
403
|
-
await driver.cleanup(processId2);
|
|
404
|
-
} else {
|
|
405
|
-
const cachedRooms = await driver.find({ processId: processId2 }, { _id: 1 });
|
|
406
|
-
logger.debug("> Removing stale rooms by processId:", processId2, `(${cachedRooms.length} rooms found)`);
|
|
407
|
-
cachedRooms.forEach((room) => room.remove());
|
|
408
|
-
}
|
|
442
|
+
await driver.cleanup(processId2);
|
|
409
443
|
}
|
|
410
444
|
async function createRoomReferences(room, init = false) {
|
|
411
445
|
rooms[room.roomId] = room;
|
|
@@ -421,29 +455,42 @@ async function createRoomReferences(room, init = false) {
|
|
|
421
455
|
}
|
|
422
456
|
return true;
|
|
423
457
|
}
|
|
424
|
-
async function
|
|
458
|
+
async function concurrentJoinOrCreateRoomLock(handler, concurrencyKey, callback) {
|
|
425
459
|
return new Promise(async (resolve, reject) => {
|
|
426
|
-
const
|
|
427
|
-
const concurrency = await presence.
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
}
|
|
437
|
-
setTimeout(async () => {
|
|
460
|
+
const hkey = getConcurrencyHashKey(handler.name);
|
|
461
|
+
const concurrency = await presence.hincrbyex(
|
|
462
|
+
hkey,
|
|
463
|
+
concurrencyKey,
|
|
464
|
+
1,
|
|
465
|
+
// increment by 1
|
|
466
|
+
MAX_CONCURRENT_CREATE_ROOM_WAIT_TIME * 2
|
|
467
|
+
// expire in 2x the time of MAX_CONCURRENT_CREATE_ROOM_WAIT_TIME
|
|
468
|
+
) - 1;
|
|
469
|
+
const fulfill = async (roomId) => {
|
|
438
470
|
try {
|
|
439
|
-
|
|
440
|
-
resolve(result);
|
|
471
|
+
resolve(await callback(roomId));
|
|
441
472
|
} catch (e) {
|
|
442
473
|
reject(e);
|
|
443
474
|
} finally {
|
|
444
|
-
await presence.
|
|
475
|
+
await presence.hincrby(hkey, concurrencyKey, -1);
|
|
445
476
|
}
|
|
446
|
-
}
|
|
477
|
+
};
|
|
478
|
+
if (concurrency > 0) {
|
|
479
|
+
debugMatchMaking(
|
|
480
|
+
"receiving %d concurrent joinOrCreate for '%s' (%s)",
|
|
481
|
+
concurrency,
|
|
482
|
+
handler.name,
|
|
483
|
+
concurrencyKey
|
|
484
|
+
);
|
|
485
|
+
const result = await presence.brpop(
|
|
486
|
+
`l:${handler.name}:${concurrencyKey}`,
|
|
487
|
+
MAX_CONCURRENT_CREATE_ROOM_WAIT_TIME + Math.min(concurrency, 3) * 0.2
|
|
488
|
+
// add extra milliseconds for each concurrent request
|
|
489
|
+
);
|
|
490
|
+
return await fulfill(result && result[1]);
|
|
491
|
+
} else {
|
|
492
|
+
return await fulfill();
|
|
493
|
+
}
|
|
447
494
|
});
|
|
448
495
|
}
|
|
449
496
|
function onClientJoinRoom(room, client) {
|
|
@@ -468,24 +515,24 @@ function onVisibilityChange(room, isInvisible) {
|
|
|
468
515
|
handlers[room.roomName].emit("visibility-change", room, isInvisible);
|
|
469
516
|
}
|
|
470
517
|
async function disposeRoom(roomName, room) {
|
|
471
|
-
debugMatchMaking("disposing '%s' (%s) on processId '%s' (graceful shutdown: %s)", roomName, room.roomId, processId,
|
|
472
|
-
|
|
473
|
-
|
|
518
|
+
debugMatchMaking("disposing '%s' (%s) on processId '%s' (graceful shutdown: %s)", roomName, room.roomId, processId, state === 2 /* SHUTTING_DOWN */);
|
|
519
|
+
room.listing.remove();
|
|
520
|
+
stats.local.roomCount--;
|
|
521
|
+
if (state !== 2 /* SHUTTING_DOWN */) {
|
|
474
522
|
stats.persist();
|
|
475
523
|
if (isDevMode) {
|
|
476
524
|
await presence.hdel(getRoomRestoreListKey(), room.roomId);
|
|
477
525
|
}
|
|
478
526
|
}
|
|
479
527
|
handlers[roomName].emit("dispose", room);
|
|
480
|
-
presence.del(getHandlerConcurrencyKey(roomName));
|
|
481
528
|
presence.unsubscribe(getRoomChannel(room.roomId));
|
|
482
529
|
delete rooms[room.roomId];
|
|
483
530
|
}
|
|
484
531
|
function getRoomChannel(roomId) {
|
|
485
532
|
return `$${roomId}`;
|
|
486
533
|
}
|
|
487
|
-
function
|
|
488
|
-
return `
|
|
534
|
+
function getConcurrencyHashKey(roomName) {
|
|
535
|
+
return `ch:${roomName}`;
|
|
489
536
|
}
|
|
490
537
|
function getProcessChannel(id = processId) {
|
|
491
538
|
return `p:${id}`;
|
|
@@ -493,7 +540,6 @@ function getProcessChannel(id = processId) {
|
|
|
493
540
|
export {
|
|
494
541
|
MatchMakerState,
|
|
495
542
|
accept,
|
|
496
|
-
cleanupStaleRooms,
|
|
497
543
|
controller,
|
|
498
544
|
create,
|
|
499
545
|
createRoom,
|
|
@@ -502,6 +548,7 @@ export {
|
|
|
502
548
|
driver,
|
|
503
549
|
findOneRoomAvailable,
|
|
504
550
|
getHandler,
|
|
551
|
+
getLocalRoomById,
|
|
505
552
|
getRoomById,
|
|
506
553
|
getRoomClass,
|
|
507
554
|
gracefullyShutdown,
|
|
@@ -509,7 +556,6 @@ export {
|
|
|
509
556
|
hasHandler,
|
|
510
557
|
healthCheckAllProcesses,
|
|
511
558
|
healthCheckProcessId,
|
|
512
|
-
isGracefullyShuttingDown,
|
|
513
559
|
join,
|
|
514
560
|
joinById,
|
|
515
561
|
joinOrCreate,
|
|
@@ -523,6 +569,7 @@ export {
|
|
|
523
569
|
removeRoomType,
|
|
524
570
|
reserveSeatFor,
|
|
525
571
|
selectProcessIdToCreateRoom,
|
|
572
|
+
setHealthChecksEnabled,
|
|
526
573
|
setup,
|
|
527
574
|
state,
|
|
528
575
|
stats
|