Kaynağa Gözat

Always keep at least one lobby open

Clément Wolf 5 ay önce
ebeveyn
işleme
6a699073bd
6 değiştirilmiş dosya ile 77 ekleme ve 73 silme
  1. 8 7
      database.js
  2. 2 61
      index.js
  3. 2 0
      ranked.js
  4. 62 0
      supervisor.js
  5. 2 3
      website_api.js
  6. 1 2
      website_ssr.js

+ 8 - 7
database.js

@@ -78,13 +78,14 @@ db.exec(`
 
 
   CREATE TABLE IF NOT EXISTS match (
-    match_id   INTEGER PRIMARY KEY,
-    invite_id  INTEGER,
-    name       TEXT,
-    ruleset    INTEGER NOT NULL DEFAULT 0,
-    data       TEXT    NOT NULL DEFAULT '{}',
-    start_time INTEGER NOT NULL,
-    end_time   INTEGER
+    match_id    INTEGER PRIMARY KEY,
+    invite_id   INTEGER,
+    name        TEXT,
+    ruleset     INTEGER NOT NULL DEFAULT 0,
+    data        TEXT    NOT NULL DEFAULT '{}',
+    start_time  INTEGER NOT NULL,
+    end_time    INTEGER,
+    reopened_as INTEGER
   );
 
   CREATE INDEX IF NOT EXISTS match_endtms_idx ON match (end_time);

+ 2 - 61
index.js

@@ -6,69 +6,10 @@ import db from './database.js';
 import {init as init_discord_interactions} from './discord_interactions.js';
 import {init as init_discord_updates} from './discord_updates.js';
 import {listen as website_listen} from './website.js';
-import {init_lobby} from './ranked.js';
 import Config from './util/config.js';
 import {capture_sentry_exception} from './util/helpers.js';
 import {update_division_tresholds} from './elo_cache.js';
-
-
-async function rejoin_lobbies() {
-  const rejoin_lobby = async (match) => {
-    console.info(`Rejoining lobby #${match.match_id}`);
-
-    try {
-      const bancho_lobby = await bancho.join('#mp_' + match.match_id);
-      await init_lobby(bancho_lobby, JSON.parse(match.data), false);
-    } catch (err) {
-      console.error(`Failed to rejoin lobby #${match.match_id}: ${err}`);
-      db.prepare(`UPDATE match SET end_time = ? WHERE match_id = ?`).run(Date.now(), match.match_id);
-
-      console.info(`Recreating lobby #${match.match_id}`);
-      try {
-        const new_lobby = await bancho.make('New o!RL lobby');
-        await init_lobby(new_lobby, JSON.parse(match.data), true);
-      } catch (err) {
-        console.error(`Failed to recreate lobby #${match.match_id}: ${err}`);
-      }
-    }
-  };
-
-  const lobbies = db.prepare(`SELECT * FROM match WHERE end_time IS NULL`).all();
-  if (lobbies.length == 0 && Config.IS_PRODUCTION) {
-    try {
-      console.info('Creating default lobby...');
-      const lobby = await bancho.make('JOIN NOW | o!RL Auto map select');
-      await init_lobby(
-          lobby,
-          {
-            creator: 'botkiwec',
-            creator_id: 29343500,
-            ruleset: 0,
-            title: '$avg_stars* | o!RL Auto map select (!info)',
-            map_selection_algo: 'pp',
-            map_pool: 'leaderboarded',
-            mods: 0,
-            mod_list: [],
-            freemod: true,
-            min_stars: 0,
-            max_stars: 11,
-            filter_query: '1 AND length > 60 AND length < 500 AND ar > 8.9 AND ar < 11',
-            nb_non_repeating: 100,
-            pp_closeness: 50,
-          },
-          true,
-      );
-    } catch (err) {
-      console.error('Failed to create default lobby:', err.message);
-    }
-  } else {
-    const promises = [];
-    for (const lobby of lobbies) {
-      promises.push(rejoin_lobby(lobby));
-    }
-    await Promise.all(promises);
-  }
-}
+import {auto_rejoin_lobbies} from './supervisor.js';
 
 
 async function init_discord() {
@@ -123,7 +64,7 @@ async function main() {
       process.exit();
     });
     await bancho.connect();
-    await rejoin_lobbies();
+    await auto_rejoin_lobbies();
   }
 
   console.log('All ready and fired up!');

+ 2 - 0
ranked.js

@@ -7,6 +7,7 @@ import {save_game_and_update_rating} from './elo.js';
 import Config from './util/config.js';
 import {capture_sentry_exception} from './util/helpers.js';
 import {get_map_info} from './map_scanner.js';
+import {auto_rejoin_lobbies} from './supervisor.js';
 
 
 function get_new_title(lobby) {
@@ -327,6 +328,7 @@ async function init_lobby(lobby, data, created_just_now) {
   generate_map_pool_table(lobby);
   lobby.on('close', () => {
     db.prepare(`DROP TABLE temp.pool_${lobby.id}`).run();
+    if (bancho.joined_lobbies.length == 0) auto_rejoin_lobbies();
   });
 
   lobby.on('settings', async () => {

+ 62 - 0
supervisor.js

@@ -0,0 +1,62 @@
+import bancho from './bancho.js';
+import db from './database.js';
+import {init_lobby} from './ranked.js';
+
+
+// Create a new bancho match, and copy existing lobby settings
+async function reopen_lobby(match) {
+  console.info(`Recreating lobby #${match.match_id}`);
+
+  const new_lobby = await bancho.make('New o!RL lobby');
+  await init_lobby(new_lobby, JSON.parse(match.data), true);
+  db.prepare(`UPDATE match SET reopened_as = ? WHERE match_id = ?`).run(new_lobby.id, match.match_id);
+  return new_lobby;
+}
+
+// Join an existing bancho match, or recreate it if it no longer exists
+async function rejoin_lobby(match) {
+  console.info(`Rejoining lobby #${match.match_id}`);
+
+  let new_lobby = null;
+  try {
+    const bancho_lobby = await bancho.join('#mp_' + match.match_id);
+    new_lobby = await init_lobby(bancho_lobby, JSON.parse(match.data), false);
+  } catch (err) {
+    console.error(`Failed to rejoin lobby #${match.match_id}: ${err}`);
+    db.prepare(`UPDATE match SET end_time = ? WHERE match_id = ?`).run(Date.now(), match.match_id);
+
+    try {
+      new_lobby = await reopen_lobby(match);
+    } catch (err) {
+      console.error(`Failed to reopen lobby #${match.match_id}: ${err}`);
+    }
+  }
+
+  return new_lobby;
+}
+
+// Rejoin lobbies if none are open
+async function auto_rejoin_lobbies() {
+  if (bancho.joined_lobbies.length > 0) return;
+
+  const lobbies = db.prepare(`SELECT * FROM match WHERE end_time IS NULL`).all();
+  if (lobbies.length > 0) {
+    // Bancho restarted, we need to recreate all the lobbies that got closed just now
+    const promises = [];
+    for (const lobby of lobbies) {
+      promises.push(rejoin_lobby(lobby));
+    }
+    await Promise.all(promises);
+  } else {
+    // All lobbies got closed, we need to reopen at least one lobby for convenience
+    try {
+      const last_lobby = db.prepare(`SELECT * FROM match WHERE reopened_as IS NULL ORDER BY end_time DESC LIMIT 1`).get();
+      if (!last_lobby) throw new Error('You need to create the first lobby manually');
+      await reopen_lobby(last_lobby);
+    } catch (err) {
+      console.error(`Failed to create default lobby: ${err}`);
+    }
+  }
+}
+
+export {auto_rejoin_lobbies};

+ 2 - 3
website_api.js

@@ -160,8 +160,7 @@ function validate_lobby_settings(settings) {
 
 
 function get_mode(req) {
-  console.debug(req.subdomains);
-  const ruleset = req.subdomains[0];
+  const ruleset = req.subdomains[0] || 'osu';
   if (ruleset == 'osu') {
     return 0;
   } else if (ruleset == 'taiko') {
@@ -398,7 +397,7 @@ async function register_routes(app) {
 
     const closed_lobbies = db.prepare(`
       SELECT * FROM match
-      WHERE ruleset = ? AND end_time IS NOT NULL
+      WHERE ruleset = ? AND reopened_as IS NULL AND end_time IS NOT NULL
       ORDER BY end_time DESC LIMIT 6`,
     ).all(mode);
     for (const lobby of closed_lobbies) {

+ 1 - 2
website_ssr.js

@@ -32,8 +32,7 @@ function mini_cache(res) {
 }
 
 function get_mode(req) {
-  console.debug(req.subdomains);
-  const ruleset = req.subdomains[0];
+  const ruleset = req.subdomains[0] || 'osu';
   if (ruleset == 'osu') {
     return 0;
   } else if (ruleset == 'taiko') {