Avoid possible panic in Room::most_active_project

Max Brunsfeld created

Participants' locations might momentarily reference projects that have already been unshared.

Change summary

crates/call/src/room.rs | 25 ++++++++++++++-----------
1 file changed, 14 insertions(+), 11 deletions(-)

Detailed changes

crates/call/src/room.rs 🔗

@@ -600,27 +600,30 @@ impl Room {
 
     /// Returns the most 'active' projects, defined as most people in the project
     pub fn most_active_project(&self) -> Option<(u64, u64)> {
-        let mut projects = HashMap::default();
-        let mut hosts = HashMap::default();
+        let mut project_hosts_and_guest_counts = HashMap::<u64, (Option<u64>, u32)>::default();
         for participant in self.remote_participants.values() {
             match participant.location {
                 ParticipantLocation::SharedProject { project_id } => {
-                    *projects.entry(project_id).or_insert(0) += 1;
+                    project_hosts_and_guest_counts
+                        .entry(project_id)
+                        .or_default()
+                        .1 += 1;
                 }
                 ParticipantLocation::External | ParticipantLocation::UnsharedProject => {}
             }
             for project in &participant.projects {
-                *projects.entry(project.id).or_insert(0) += 1;
-                hosts.insert(project.id, participant.user.id);
+                project_hosts_and_guest_counts
+                    .entry(project.id)
+                    .or_default()
+                    .0 = Some(participant.user.id);
             }
         }
 
-        let mut pairs: Vec<(u64, usize)> = projects.into_iter().collect();
-        pairs.sort_by_key(|(_, count)| *count as i32);
-
-        pairs
-            .first()
-            .map(|(project_id, _)| (*project_id, hosts[&project_id]))
+        project_hosts_and_guest_counts
+            .into_iter()
+            .filter_map(|(id, (host, guest_count))| Some((id, host?, guest_count)))
+            .max_by_key(|(_, _, guest_count)| *guest_count)
+            .map(|(id, host, _)| (id, host))
     }
 
     async fn handle_room_updated(