Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perform partial room unloads when monolith is shutting down #1183

Merged
merged 1 commit into from
Dec 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions deploy/fly.prod.monolith.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
app = "ott-prod"
primary_region = "ewr"
kill_timeout = 15

[build]
dockerfile = "monolith.Dockerfile"
Expand Down
1 change: 1 addition & 0 deletions deploy/fly.staging.monolith.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
app = "ott-staging"
primary_region = "ewr"
kill_timeout = 15

[build]
dockerfile = "monolith.Dockerfile"
Expand Down
56 changes: 41 additions & 15 deletions server/roommanager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,23 @@
bus.emit("load", room.name);
}

let updaterInterval: NodeJS.Timer | null = null;
export async function start() {
log.info("Starting room manager");

setInterval(update, 1000);
updaterInterval = setInterval(update, 1000);
process.on("SIGINT", shutdown);
process.on("SIGTERM", shutdown);
}

async function shutdown() {
log.info("Shutting down room manager");
if (updaterInterval) {
clearInterval(updaterInterval);
updaterInterval = null;

Check warning on line 59 in server/roommanager.ts

View check run for this annotation

Codecov / codecov/patch

server/roommanager.ts#L55-L59

Added lines #L55 - L59 were not covered by tests
}
await Promise.all(rooms.map(room => unloadRoom(room.name, { preserveRedis: true })));
process.exit(0);

Check warning on line 62 in server/roommanager.ts

View check run for this annotation

Codecov / codecov/patch

server/roommanager.ts#L61-L62

Added lines #L61 - L62 were not covered by tests
}

export function redisStateToState(state: RoomStateFromRedis): RoomState {
Expand Down Expand Up @@ -151,23 +164,36 @@
return ok(room);
}

export async function unloadRoom(roomName: string): Promise<void> {
export async function unloadRoom(
room: string | Room,
options: Partial<{ preserveRedis: boolean }> = {}
): Promise<void> {
const opts = _.defaults(options, {
preserveRedis: false,
});

let idx = -1;
for (let i = 0; i < rooms.length; i++) {
if (rooms[i].name.toLowerCase() === roomName.toLowerCase()) {
idx = i;
break;
if (typeof room === "string") {
for (let i = 0; i < rooms.length; i++) {
if (rooms[i].name.toLowerCase() === room.toLowerCase()) {
idx = i;
break;
}
}
if (idx < 0) {
throw new RoomNotFoundException(room);
}
room = rooms[idx];
}
if (idx >= 0) {
log.info(`Unloading room: ${roomName}`);
await rooms[idx].onBeforeUnload();
} else {
throw new RoomNotFoundException(roomName);
}
const roomName = room.name;
log.info(`Unloading room: ${roomName}`);
await room.onBeforeUnload();
idx = rooms[idx].name === room.name ? idx : rooms.indexOf(room); // because the index may have changed across await boundaries
rooms.splice(idx, 1);
await redisClient.del(`room:${roomName}`);
await redisClient.del(`room-sync:${roomName}`);
if (!opts.preserveRedis) {
await redisClient.del(`room:${roomName}`);
await redisClient.del(`room-sync:${roomName}`);
}
bus.emit("unload", roomName);
}

Expand All @@ -184,7 +210,7 @@
/** Unload all rooms off of this node. Intended to only be used in tests. */
export async function unloadAllRooms(): Promise<void> {
const names = rooms.map(r => r.name);
await Promise.all(names.map(unloadRoom));
await Promise.all(names.map(name => unloadRoom(name)));
}

export function publish(roomName: string, msg: ServerMessage) {
Expand Down
Loading