From ba40af8324fdd46c918a6d5e4b6abd8a5371482e Mon Sep 17 00:00:00 2001
From: Richard Alam <ritzalam@gmail.com>
Date: Fri, 23 Apr 2021 23:22:01 +0000
Subject: [PATCH]  - let parent meeting manage breakout lifecycle

---
 .../scala/org/bigbluebutton/core/api/InMessages.scala  |  2 +-
 .../apps/breakout/EndAllBreakoutRoomsMsgHdlr.scala     |  4 ++--
 .../apps/breakout/EndBreakoutRoomInternalMsgHdlr.scala |  3 +--
 .../SendBreakoutTimeRemainingInternalMsgHdlr.scala     |  2 +-
 .../apps/users/LogoutAndEndMeetingCmdMsgHdlr.scala     |  2 +-
 .../org/bigbluebutton/core/domain/MeetingState2x.scala |  3 ++-
 .../bigbluebutton/core/running/HandlerHelpers.scala    |  4 ++--
 .../org/bigbluebutton/core/running/MeetingActor.scala  | 10 +++++++---
 .../core/running/MeetingExpiryTrackerHelper.scala      |  2 +-
 .../handlers/SendBreakoutTimeRemainingMsgHdlr.scala    |  6 +++++-
 .../message/handlers/SendTimeRemainingUpdateHdlr.scala |  2 +-
 .../handlers/meeting/EndMeetingSysCmdMsgHdlr.scala     |  2 +-
 12 files changed, 25 insertions(+), 17 deletions(-)

diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/api/InMessages.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/api/InMessages.scala
index c08cb4ad4a..59132fca0e 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/api/InMessages.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/api/InMessages.scala
@@ -73,7 +73,7 @@ case class BreakoutRoomUsersUpdateInternalMsg(parentId: String, breakoutId: Stri
  * @param parentId
  * @param breakoutId
  */
-case class EndBreakoutRoomInternalMsg(parentId: String, breakoutId: String) extends InMessage
+case class EndBreakoutRoomInternalMsg(parentId: String, breakoutId: String, reason: String) extends InMessage
 
 // DeskShare
 case class DeskShareStartedRequest(conferenceName: String, callerId: String, callerIdName: String) extends InMessage
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/breakout/EndAllBreakoutRoomsMsgHdlr.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/breakout/EndAllBreakoutRoomsMsgHdlr.scala
index 332a49c1b6..4f63d6828e 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/breakout/EndAllBreakoutRoomsMsgHdlr.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/breakout/EndAllBreakoutRoomsMsgHdlr.scala
@@ -3,7 +3,7 @@ package org.bigbluebutton.core.apps.breakout
 import org.bigbluebutton.common2.msgs._
 import org.bigbluebutton.core.api.EndBreakoutRoomInternalMsg
 import org.bigbluebutton.core.bus.BigBlueButtonEvent
-import org.bigbluebutton.core.domain.MeetingState2x
+import org.bigbluebutton.core.domain.{ MeetingEndReason, MeetingState2x }
 import org.bigbluebutton.core.running.{ MeetingActor, OutMsgRouter }
 import org.bigbluebutton.core.apps.{ PermissionCheck, RightsManagementTrait }
 
@@ -23,7 +23,7 @@ trait EndAllBreakoutRoomsMsgHdlr extends RightsManagementTrait {
         model <- state.breakout
       } yield {
         model.rooms.values.foreach { room =>
-          eventBus.publish(BigBlueButtonEvent(room.id, EndBreakoutRoomInternalMsg(props.breakoutProps.parentId, room.id)))
+          eventBus.publish(BigBlueButtonEvent(room.id, EndBreakoutRoomInternalMsg(props.breakoutProps.parentId, room.id, MeetingEndReason.BREAKOUT_ENDED_BY_MOD)))
         }
       }
 
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/breakout/EndBreakoutRoomInternalMsgHdlr.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/breakout/EndBreakoutRoomInternalMsgHdlr.scala
index 537f3101f6..051d9720c4 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/breakout/EndBreakoutRoomInternalMsgHdlr.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/breakout/EndBreakoutRoomInternalMsgHdlr.scala
@@ -2,7 +2,6 @@ package org.bigbluebutton.core.apps.breakout
 
 import org.bigbluebutton.core.api.EndBreakoutRoomInternalMsg
 import org.bigbluebutton.core.bus.{ InternalEventBus }
-import org.bigbluebutton.core.domain.MeetingEndReason
 import org.bigbluebutton.core.running.{ BaseMeetingActor, HandlerHelpers, LiveMeeting, OutMsgRouter }
 
 trait EndBreakoutRoomInternalMsgHdlr extends HandlerHelpers {
@@ -14,6 +13,6 @@ trait EndBreakoutRoomInternalMsgHdlr extends HandlerHelpers {
 
   def handleEndBreakoutRoomInternalMsg(msg: EndBreakoutRoomInternalMsg): Unit = {
     log.info("Breakout room {} ended by parent meeting {}.", msg.breakoutId, msg.parentId)
-    sendEndMeetingDueToExpiry(MeetingEndReason.ENDED_BY_PARENT, eventBus, outGW, liveMeeting, "system")
+    sendEndMeetingDueToExpiry(msg.reason, eventBus, outGW, liveMeeting, "system")
   }
 }
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/breakout/SendBreakoutTimeRemainingInternalMsgHdlr.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/breakout/SendBreakoutTimeRemainingInternalMsgHdlr.scala
index c3decbbf73..4d2ab49ec9 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/breakout/SendBreakoutTimeRemainingInternalMsgHdlr.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/breakout/SendBreakoutTimeRemainingInternalMsgHdlr.scala
@@ -1,7 +1,7 @@
 package org.bigbluebutton.core.apps.breakout
 
 import org.bigbluebutton.core.api.SendBreakoutTimeRemainingInternalMsg
-import org.bigbluebutton.core.running.{LiveMeeting, OutMsgRouter}
+import org.bigbluebutton.core.running.{ LiveMeeting, OutMsgRouter }
 import org.bigbluebutton.core2.message.senders.MsgBuilder
 
 trait SendBreakoutTimeRemainingInternalMsgHdlr {
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/users/LogoutAndEndMeetingCmdMsgHdlr.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/users/LogoutAndEndMeetingCmdMsgHdlr.scala
index 3ea3c95122..325378026f 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/users/LogoutAndEndMeetingCmdMsgHdlr.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/users/LogoutAndEndMeetingCmdMsgHdlr.scala
@@ -24,7 +24,7 @@ trait LogoutAndEndMeetingCmdMsgHdlr extends RightsManagementTrait {
         u <- Users2x.findWithIntId(liveMeeting.users2x, msg.body.userId)
       } yield {
         if (u.role == Roles.MODERATOR_ROLE) {
-          endAllBreakoutRooms(eventBus, liveMeeting, state)
+          endAllBreakoutRooms(eventBus, liveMeeting, state, MeetingEndReason.ENDED_AFTER_USER_LOGGED_OUT)
           log.info("Meeting {} ended by user [{}, {}} when logging out.", liveMeeting.props.meetingProp.intId,
             u.intId, u.name)
           sendEndMeetingDueToExpiry(MeetingEndReason.ENDED_AFTER_USER_LOGGED_OUT, eventBus, outGW, liveMeeting, u.intId)
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/domain/MeetingState2x.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/domain/MeetingState2x.scala
index 6a4bb41efb..ecd2c9e3ec 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/domain/MeetingState2x.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/domain/MeetingState2x.scala
@@ -29,6 +29,7 @@ object MeetingEndReason {
   val ENDED_WHEN_LAST_USER_LEFT = "ENDED_WHEN_LAST_USER_LEFT"
   val ENDED_AFTER_USER_LOGGED_OUT = "ENDED_AFTER_USER_LOGGED_OUT"
   val ENDED_AFTER_EXCEEDING_DURATION = "ENDED_AFTER_EXCEEDING_DURATION"
-  val ENDED_BY_PARENT = "ENDED_BY_PARENT"
+  val BREAKOUT_ENDED_EXCEEDING_DURATION = "BREAKOUT_ENDED_EXCEEDING_DURATION"
+  val BREAKOUT_ENDED_BY_MOD = "BREAKOUT_ENDED_BY_MOD"
   val ENDED_DUE_TO_NO_AUTHED_USER = "ENDED_DUE_TO_NO_AUTHED_USER"
 }
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/HandlerHelpers.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/HandlerHelpers.scala
index d9799d4369..53a3a444fb 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/HandlerHelpers.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/HandlerHelpers.scala
@@ -205,12 +205,12 @@ trait HandlerHelpers extends SystemConfiguration {
     outGW.send(event)
   }
 
-  def endAllBreakoutRooms(eventBus: InternalEventBus, liveMeeting: LiveMeeting, state: MeetingState2x): MeetingState2x = {
+  def endAllBreakoutRooms(eventBus: InternalEventBus, liveMeeting: LiveMeeting, state: MeetingState2x, reason: String): MeetingState2x = {
     for {
       model <- state.breakout
     } yield {
       model.rooms.values.foreach { room =>
-        eventBus.publish(BigBlueButtonEvent(room.id, EndBreakoutRoomInternalMsg(liveMeeting.props.breakoutProps.parentId, room.id)))
+        eventBus.publish(BigBlueButtonEvent(room.id, EndBreakoutRoomInternalMsg(liveMeeting.props.breakoutProps.parentId, room.id, reason)))
       }
     }
 
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingActor.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingActor.scala
index a26f62c541..23e0ee18d5 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingActor.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingActor.scala
@@ -575,9 +575,13 @@ class MeetingActor(
   def handleMonitorNumberOfUsers(msg: MonitorNumberOfUsersInternalMsg) {
     state = removeUsersWithExpiredUserLeftFlag(liveMeeting, state)
 
-    val (newState, expireReason) = ExpiryTrackerHelper.processMeetingExpiryAudit(outGW, eventBus, liveMeeting, state)
-    state = newState
-    expireReason foreach (reason => log.info("Meeting {} expired with reason {}", props.meetingProp.intId, reason))
+    if (!liveMeeting.props.meetingProp.isBreakout) {
+      // Track expiry only for non-breakout rooms. The breakout room lifecycle is
+      // driven by the parent meeting.
+      val (newState, expireReason) = ExpiryTrackerHelper.processMeetingExpiryAudit(outGW, eventBus, liveMeeting, state)
+      state = newState
+      expireReason foreach (reason => log.info("Meeting {} expired with reason {}", props.meetingProp.intId, reason))
+    }
 
     sendRttTraceTest()
     setRecordingChapterBreak()
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingExpiryTrackerHelper.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingExpiryTrackerHelper.scala
index c4338aa5ea..9d473ba27b 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingExpiryTrackerHelper.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingExpiryTrackerHelper.scala
@@ -20,7 +20,7 @@ trait MeetingExpiryTrackerHelper extends HandlerHelpers {
       for {
         expireReason <- reason
       } yield {
-        endAllBreakoutRooms(eventBus, liveMeeting, state)
+        endAllBreakoutRooms(eventBus, liveMeeting, state, expireReason)
         sendEndMeetingDueToExpiry(expireReason, eventBus, outGW, liveMeeting, "system")
       }
     }
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/message/handlers/SendBreakoutTimeRemainingMsgHdlr.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/message/handlers/SendBreakoutTimeRemainingMsgHdlr.scala
index 55116e2183..f4dc94fcb3 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/message/handlers/SendBreakoutTimeRemainingMsgHdlr.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/message/handlers/SendBreakoutTimeRemainingMsgHdlr.scala
@@ -3,7 +3,7 @@ package org.bigbluebutton.core2.message.handlers
 import org.bigbluebutton.common2.msgs._
 import org.bigbluebutton.core.api.{ EndBreakoutRoomInternalMsg, SendBreakoutTimeRemainingInternalMsg, SendTimeRemainingAuditInternalMsg }
 import org.bigbluebutton.core.bus.BigBlueButtonEvent
-import org.bigbluebutton.core.domain.MeetingState2x
+import org.bigbluebutton.core.domain.{ MeetingEndReason, MeetingState2x }
 import org.bigbluebutton.core.running.{ LiveMeeting, MeetingActor, OutMsgRouter }
 import org.bigbluebutton.core.util.TimeUtil
 
@@ -32,6 +32,10 @@ trait SendBreakoutTimeRemainingMsgHdlr {
       model.rooms.values.foreach { room =>
         eventBus.publish(BigBlueButtonEvent(room.id, SendBreakoutTimeRemainingInternalMsg(props.breakoutProps.parentId, timeRemaining.toInt)))
       }
+
+      if (timeRemaining < 0) {
+        endAllBreakoutRooms(eventBus, liveMeeting, state, MeetingEndReason.BREAKOUT_ENDED_EXCEEDING_DURATION)
+      }
     }
 
     state
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/message/handlers/SendTimeRemainingUpdateHdlr.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/message/handlers/SendTimeRemainingUpdateHdlr.scala
index e17880b90c..27c6fb14d7 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/message/handlers/SendTimeRemainingUpdateHdlr.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/message/handlers/SendTimeRemainingUpdateHdlr.scala
@@ -2,7 +2,7 @@ package org.bigbluebutton.core2.message.handlers
 
 import org.bigbluebutton.core.api.SendTimeRemainingAuditInternalMsg
 import org.bigbluebutton.core.domain.MeetingState2x
-import org.bigbluebutton.core.running.{BaseMeetingActor, LiveMeeting, OutMsgRouter}
+import org.bigbluebutton.core.running.{ BaseMeetingActor, LiveMeeting, OutMsgRouter }
 import org.bigbluebutton.core.util.TimeUtil
 import org.bigbluebutton.core2.message.senders.MsgBuilder
 
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/message/handlers/meeting/EndMeetingSysCmdMsgHdlr.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/message/handlers/meeting/EndMeetingSysCmdMsgHdlr.scala
index 21a87b2a5b..131d3031d3 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/message/handlers/meeting/EndMeetingSysCmdMsgHdlr.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/message/handlers/meeting/EndMeetingSysCmdMsgHdlr.scala
@@ -13,7 +13,7 @@ trait EndMeetingSysCmdMsgHdlr extends HandlerHelpers {
   val eventBus: InternalEventBus
 
   def handleEndMeeting(msg: EndMeetingSysCmdMsg, state: MeetingState2x): Unit = {
-    endAllBreakoutRooms(eventBus, liveMeeting, state)
+    endAllBreakoutRooms(eventBus, liveMeeting, state, MeetingEndReason.ENDED_FROM_API)
     log.info("Meeting {} ended by from API.", msg.body.meetingId)
     sendEndMeetingDueToExpiry(MeetingEndReason.ENDED_FROM_API, eventBus, outGW, liveMeeting, "system")
   }
-- 
GitLab