- update the state to keep recording timer updated

This commit is contained in:
Richard Alam 2018-05-18 11:35:30 -07:00
parent 634635c8cd
commit ef60beec7c
5 changed files with 141 additions and 103 deletions

View File

@ -12,27 +12,8 @@ trait SetRecordingStatusCmdMsgHdlr {
val liveMeeting: LiveMeeting
val outGW: OutMsgRouter
def handleSetRecordingStatusCmdMsg(msg: SetRecordingStatusCmdMsg, state: MeetingState2x) {
def handleSetRecordingStatusCmdMsg(msg: SetRecordingStatusCmdMsg, state: MeetingState2x): MeetingState2x = {
log.info("Change recording status. meetingId=" + liveMeeting.props.meetingProp.intId + " recording=" + msg.body.recording)
if (liveMeeting.props.recordProp.allowStartStopRecording &&
MeetingStatus2x.isRecording(liveMeeting.status) != msg.body.recording) {
if (msg.body.recording) {
log.debug("+++++++ Start timer {}", TimeUtil.timeNowInMs())
MeetingStatus2x.recordingStarted(liveMeeting.status)
val tracker = state.recordingTracker.startTimer(TimeUtil.timeNowInMs())
state.update(tracker)
} else {
MeetingStatus2x.recordingStopped(liveMeeting.status)
val tracker = state.recordingTracker.pauseTimer(TimeUtil.timeNowInMs())
state.update(tracker)
}
val event = buildRecordingStatusChangedEvtMsg(liveMeeting.props.meetingProp.intId, msg.body.setBy, msg.body.recording)
outGW.send(event)
}
def buildRecordingStatusChangedEvtMsg(meetingId: String, userId: String, recording: Boolean): BbbCommonEnvCoreMsg = {
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, meetingId, userId)
@ -43,5 +24,36 @@ trait SetRecordingStatusCmdMsgHdlr {
BbbCommonEnvCoreMsg(envelope, event)
}
if (liveMeeting.props.recordProp.allowStartStopRecording &&
MeetingStatus2x.isRecording(liveMeeting.status) != msg.body.recording) {
if (msg.body.recording) {
log.debug("+++++++ Start timer {}", TimeUtil.timeNowInMs())
MeetingStatus2x.recordingStarted(liveMeeting.status)
} else {
MeetingStatus2x.recordingStopped(liveMeeting.status)
}
val event = buildRecordingStatusChangedEvtMsg(liveMeeting.props.meetingProp.intId, msg.body.setBy, msg.body.recording)
outGW.send(event)
if (MeetingStatus2x.isRecording(liveMeeting.status)) {
val tracker = state.recordingTracker.startTimer(TimeUtil.timeNowInMs())
state.update(tracker)
} else {
println("pause - before: start=" + state.recordingTracker.startedOnInMs
+ " previous=" + state.recordingTracker.previousDurationInMs
+ " current=" + state.recordingTracker.currentDurationInMs)
val tracker = state.recordingTracker.pauseTimer(TimeUtil.timeNowInMs())
println("pause - after: start=" + tracker.startedOnInMs + " previous=" + tracker.previousDurationInMs + " current=" + tracker.currentDurationInMs)
state.update(tracker)
}
} else {
state
}
}
}

View File

@ -1,11 +1,12 @@
package org.bigbluebutton.core.domain
case class MeetingInactivityTracker(
val maxInactivityTimeoutInMs: Long,
val warningBeforeMaxInMs: Long,
lastActivityTimestampInMs: Long,
warningSent: Boolean,
warningSentOnTimestampInMs: Long) {
val maxInactivityTimeoutInMs: Long,
val warningBeforeMaxInMs: Long,
lastActivityTimestampInMs: Long,
warningSent: Boolean,
warningSentOnTimestampInMs: Long
) {
def setWarningSentAndTimestamp(nowInMs: Long): MeetingInactivityTracker = {
copy(warningSent = true, warningSentOnTimestampInMs = nowInMs)
}
@ -32,12 +33,13 @@ case class MeetingInactivityTracker(
}
case class MeetingExpiryTracker(
startedOnInMs: Long,
userHasJoined: Boolean,
lastUserLeftOnInMs: Option[Long],
durationInMs: Long,
meetingExpireIfNoUserJoinedInMs: Long,
meetingExpireWhenLastUserLeftInMs: Long) {
startedOnInMs: Long,
userHasJoined: Boolean,
lastUserLeftOnInMs: Option[Long],
durationInMs: Long,
meetingExpireIfNoUserJoinedInMs: Long,
meetingExpireWhenLastUserLeftInMs: Long
) {
def setUserHasJoined(): MeetingExpiryTracker = {
if (!userHasJoined) {
copy(userHasJoined = true, lastUserLeftOnInMs = None)
@ -90,9 +92,10 @@ case class MeetingExpiryTracker(
}
case class MeetingRecordingTracker(
startedOnInMs: Long,
previousDurationInMs: Long,
currentDurationInMs: Long) {
startedOnInMs: Long,
previousDurationInMs: Long,
currentDurationInMs: Long
) {
def startTimer(nowInMs: Long): MeetingRecordingTracker = {
copy(startedOnInMs = nowInMs)

View File

@ -41,7 +41,8 @@ trait HandlerHelpers extends SystemConfiguration {
emoji = "none",
presenter = false,
locked = MeetingStatus2x.getPermissions(liveMeeting.status).lockOnJoin,
avatar = regUser.avatarURL)
avatar = regUser.avatarURL
)
}
nu match {
@ -81,7 +82,8 @@ trait HandlerHelpers extends SystemConfiguration {
val event = buildRecordingStatusChangedEvtMsg(
liveMeeting.props.meetingProp.intId,
"system", MeetingStatus2x.isRecording(liveMeeting.status))
"system", MeetingStatus2x.isRecording(liveMeeting.status)
)
outGW.send(event)
}
@ -105,7 +107,8 @@ trait HandlerHelpers extends SystemConfiguration {
val event = buildRecordingStatusChangedEvtMsg(
liveMeeting.props.meetingProp.intId,
"system", MeetingStatus2x.isRecording(liveMeeting.status))
"system", MeetingStatus2x.isRecording(liveMeeting.status)
)
outGW.send(event)
}
}
@ -165,7 +168,8 @@ trait HandlerHelpers extends SystemConfiguration {
if (liveMeeting.props.meetingProp.isBreakout) {
eventBus.publish(BigBlueButtonEvent(
liveMeeting.props.breakoutProps.parentId,
new BreakoutRoomEndedInternalMsg(liveMeeting.props.meetingProp.intId)))
new BreakoutRoomEndedInternalMsg(liveMeeting.props.meetingProp.intId)
))
}
}
@ -205,7 +209,8 @@ trait HandlerHelpers extends SystemConfiguration {
if (liveMeeting.props.meetingProp.isBreakout) {
eventBus.publish(BigBlueButtonEvent(
liveMeeting.props.breakoutProps.parentId,
new BreakoutRoomEndedInternalMsg(meetingId)))
new BreakoutRoomEndedInternalMsg(meetingId)
))
}
val event = MsgBuilder.buildEjectAllFromVoiceConfMsg(meetingId, liveMeeting.props.voiceProp.voiceConf)

View File

@ -41,7 +41,8 @@ object MeetingActor {
props: DefaultProps,
eventBus: InternalEventBus,
outGW: OutMsgRouter,
liveMeeting: LiveMeeting): Props =
liveMeeting: LiveMeeting
): Props =
Props(classOf[MeetingActor], props, eventBus, outGW, liveMeeting)
}
@ -49,36 +50,37 @@ class MeetingActor(
val props: DefaultProps,
val eventBus: InternalEventBus,
val outGW: OutMsgRouter,
val liveMeeting: LiveMeeting)
extends BaseMeetingActor
with GuestsApp
with LayoutApp2x
with VoiceApp2x
with PollApp2x
with BreakoutApp2x
with UsersApp2x
with WhiteboardApp2x
val liveMeeting: LiveMeeting
)
extends BaseMeetingActor
with GuestsApp
with LayoutApp2x
with VoiceApp2x
with PollApp2x
with BreakoutApp2x
with UsersApp2x
with WhiteboardApp2x
with PermisssionCheck
with UserBroadcastCamStartMsgHdlr
with UserJoinMeetingReqMsgHdlr
with UserJoinMeetingAfterReconnectReqMsgHdlr
with UserBroadcastCamStopMsgHdlr
with UserConnectedToGlobalAudioMsgHdlr
with UserDisconnectedFromGlobalAudioMsgHdlr
with MuteAllExceptPresentersCmdMsgHdlr
with MuteMeetingCmdMsgHdlr
with IsMeetingMutedReqMsgHdlr
with MuteUserCmdMsgHdlr
with EjectUserFromVoiceCmdMsgHdlr
with EndMeetingSysCmdMsgHdlr
with DestroyMeetingSysCmdMsgHdlr
with SendTimeRemainingUpdateHdlr
with SendBreakoutTimeRemainingMsgHdlr
with ChangeLockSettingsInMeetingCmdMsgHdlr
with ValidateConnAuthTokenSysMsgHdlr
with SyncGetMeetingInfoRespMsgHdlr
with ClientToServerLatencyTracerMsgHdlr {
with PermisssionCheck
with UserBroadcastCamStartMsgHdlr
with UserJoinMeetingReqMsgHdlr
with UserJoinMeetingAfterReconnectReqMsgHdlr
with UserBroadcastCamStopMsgHdlr
with UserConnectedToGlobalAudioMsgHdlr
with UserDisconnectedFromGlobalAudioMsgHdlr
with MuteAllExceptPresentersCmdMsgHdlr
with MuteMeetingCmdMsgHdlr
with IsMeetingMutedReqMsgHdlr
with MuteUserCmdMsgHdlr
with EjectUserFromVoiceCmdMsgHdlr
with EndMeetingSysCmdMsgHdlr
with DestroyMeetingSysCmdMsgHdlr
with SendTimeRemainingUpdateHdlr
with SendBreakoutTimeRemainingMsgHdlr
with ChangeLockSettingsInMeetingCmdMsgHdlr
with ValidateConnAuthTokenSysMsgHdlr
with SyncGetMeetingInfoRespMsgHdlr
with ClientToServerLatencyTracerMsgHdlr {
override val supervisorStrategy = OneForOneStrategy(maxNrOfRetries = 10, withinTimeRange = 1 minute) {
case e: Exception => {
@ -96,7 +98,8 @@ class MeetingActor(
*/
var actorMonitor = context.actorOf(
MeetingActorAudit.props(props, eventBus, outGW),
"actorMonitor-" + props.meetingProp.intId)
"actorMonitor-" + props.meetingProp.intId
)
val presentationApp2x = new PresentationApp2x(liveMeeting, outGW)
val screenshareApp2x = new ScreenshareApp2x(liveMeeting, outGW)
@ -112,7 +115,8 @@ class MeetingActor(
TimeUtil.minutesToMillis(props.durationProps.warnMinutesBeforeMax),
lastActivityTimestampInMs = TimeUtil.timeNowInMs(),
warningSent = false,
warningSentOnTimestampInMs = 0L)
warningSentOnTimestampInMs = 0L
)
val expiryTracker = new MeetingExpiryTracker(
startedOnInMs = TimeUtil.timeNowInMs(),
@ -120,7 +124,8 @@ class MeetingActor(
lastUserLeftOnInMs = None,
durationInMs = TimeUtil.minutesToMillis(props.durationProps.duration),
meetingExpireIfNoUserJoinedInMs = TimeUtil.minutesToMillis(props.durationProps.meetingExpireIfNoUserJoinedInMinutes),
meetingExpireWhenLastUserLeftInMs = TimeUtil.minutesToMillis(props.durationProps.meetingExpireWhenLastUserLeftInMinutes))
meetingExpireWhenLastUserLeftInMs = TimeUtil.minutesToMillis(props.durationProps.meetingExpireWhenLastUserLeftInMinutes)
)
val recordingTracker = new MeetingRecordingTracker(startedOnInMs = 0, previousDurationInMs = 0, currentDurationInMs = 0)
@ -138,10 +143,10 @@ class MeetingActor(
// Set webcamsOnlyForModerator property in case we didn't after meeting creation
MeetingStatus2x.setWebcamsOnlyForModerator(liveMeeting.status, liveMeeting.props.usersProp.webcamsOnlyForModerator)
/*******************************************************************/
/*******************************************************************/
//object FakeTestData extends FakeTestData
//FakeTestData.createFakeUsers(liveMeeting)
/*******************************************************************/
/*******************************************************************/
def receive = {
//=============================
@ -179,9 +184,10 @@ class MeetingActor(
// Screenshare
case msg: DeskShareGetDeskShareInfoRequest => handleDeskShareGetDeskShareInfoRequest(msg)
case msg: SendRecordingTimerInternalMsg => handleSendRecordingTimerInternalMsg(msg)
case msg: SendRecordingTimerInternalMsg =>
state = handleSendRecordingTimerInternalMsg(msg, state)
case _ => // do nothing
case _ => // do nothing
}
private def handleBbbCommonEnvCoreMsg(msg: BbbCommonEnvCoreMsg): Unit = {
@ -205,8 +211,9 @@ class MeetingActor(
case m: UserJoinedVoiceConfEvtMsg => handleUserJoinedVoiceConfEvtMsg(m)
case m: MeetingActivityResponseCmdMsg =>
state = usersApp.handleMeetingActivityResponseCmdMsg(m, state)
case m: LogoutAndEndMeetingCmdMsg => usersApp.handleLogoutAndEndMeetingCmdMsg(m, state)
case m: SetRecordingStatusCmdMsg => usersApp.handleSetRecordingStatusCmdMsg(m, state)
case m: LogoutAndEndMeetingCmdMsg => usersApp.handleLogoutAndEndMeetingCmdMsg(m, state)
case m: SetRecordingStatusCmdMsg =>
state = usersApp.handleSetRecordingStatusCmdMsg(m, state)
case m: GetWebcamsOnlyForModeratorReqMsg => usersApp.handleGetWebcamsOnlyForModeratorReqMsg(m)
case m: UpdateWebcamsOnlyForModeratorCmdMsg => usersApp.handleUpdateWebcamsOnlyForModeratorCmdMsg(m)
case m: GetRecordingStatusReqMsg => usersApp.handleGetRecordingStatusReqMsg(m)
@ -344,7 +351,8 @@ class MeetingActor(
// request screenshare to end
screenshareApp2x.handleScreenshareStoppedVoiceConfEvtMsg(
liveMeeting.props.voiceProp.voiceConf,
liveMeeting.props.screenshareProps.screenshareConf)
liveMeeting.props.screenshareProps.screenshareConf
)
}
@ -374,24 +382,8 @@ class MeetingActor(
sendRttTraceTest()
}
def handleSendRecordingTimerInternalMsg(msg: SendRecordingTimerInternalMsg) {
def buildUpdateReocrdingTimerEvtMsg(meetingId: String): BbbCommonEnvCoreMsg = {
log.debug("$$$$$$$ Meeting is recording {}", MeetingStatus2x.isRecording(liveMeeting.status))
var newDuration: Long = 0
if (MeetingStatus2x.isRecording(liveMeeting.status)) {
newDuration = TimeUtil.timeNowInMs()
}
log.debug("====== New duration {}", newDuration)
val tracker = state.recordingTracker.udpateCurrentDuration(newDuration)
state.update(tracker)
val recordingTime = TimeUtil.millisToSeconds(tracker.recordingDuration())
log.debug("##### Recorded seconds {}", recordingTime)
def handleSendRecordingTimerInternalMsg(msg: SendRecordingTimerInternalMsg, state: MeetingState2x): MeetingState2x = {
def buildUpdateReocrdingTimerEvtMsg(meetingId: String, recordingTime: Long): BbbCommonEnvCoreMsg = {
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, meetingId, "not-used")
val envelope = BbbCoreEnvelope(UpdateRecordingTimerEvtMsg.NAME, routing)
val body = UpdateRecordingTimerEvtMsgBody(recordingTime)
@ -403,8 +395,30 @@ class MeetingActor(
log.debug("##### Sending UpdateReocrdingTimerEvtMsg")
val event = buildUpdateReocrdingTimerEvtMsg(liveMeeting.props.meetingProp.intId)
log.debug("$$$$$$$ Meeting is recording {}", MeetingStatus2x.isRecording(liveMeeting.status))
var newDuration: Long = 0
if (MeetingStatus2x.isRecording(liveMeeting.status)) {
newDuration = TimeUtil.timeNowInMs()
}
log.debug("====== New duration {}", newDuration)
println("update - before: start=" + state.recordingTracker.startedOnInMs
+ " previous=" + state.recordingTracker.previousDurationInMs
+ " current=" + state.recordingTracker.currentDurationInMs)
val tracker = state.recordingTracker.udpateCurrentDuration(newDuration)
println("update - before: start=" + tracker.startedOnInMs + " previous=" + tracker.previousDurationInMs + " current=" + tracker.currentDurationInMs)
val newState = state.update(tracker)
val recordingTime = TimeUtil.millisToSeconds(tracker.recordingDuration())
log.debug("##### Recorded seconds {}", recordingTime)
val event = buildUpdateReocrdingTimerEvtMsg(liveMeeting.props.meetingProp.intId, recordingTime)
outGW.send(event)
newState
}
def sendRttTraceTest(): Unit = {

View File

@ -18,7 +18,8 @@ object MeetingActorAudit {
def props(
props: DefaultProps,
eventBus: InternalEventBus,
outGW: OutMsgRouter): Props =
outGW: OutMsgRouter
): Props =
Props(classOf[MeetingActorAudit], props, eventBus, outGW)
}
@ -26,8 +27,9 @@ object MeetingActorAudit {
// periodically sends messages to the meeting actor
class MeetingActorAudit(
val props: DefaultProps,
val eventBus: InternalEventBus, val outGW: OutMsgRouter)
extends Actor with ActorLogging with SystemConfiguration with AuditHelpers {
val eventBus: InternalEventBus, val outGW: OutMsgRouter
)
extends Actor with ActorLogging with SystemConfiguration with AuditHelpers {
object AuditMonitorInternalMsg
@ -52,7 +54,8 @@ class MeetingActorAudit(
// This is a breakout room. Inform our parent meeting that we have been successfully created.
eventBus.publish(BigBlueButtonEvent(
props.breakoutProps.parentId,
BreakoutRoomCreatedInternalMsg(props.breakoutProps.parentId, props.meetingProp.intId)))
BreakoutRoomCreatedInternalMsg(props.breakoutProps.parentId, props.meetingProp.intId)
))
}
@ -73,7 +76,8 @@ class MeetingActorAudit(
// This is a breakout room. Update the main meeting with list of users in this breakout room.
eventBus.publish(BigBlueButtonEvent(
props.meetingProp.intId,
SendBreakoutUsersAuditInternalMsg(props.breakoutProps.parentId, props.meetingProp.intId)))
SendBreakoutUsersAuditInternalMsg(props.breakoutProps.parentId, props.meetingProp.intId)
))
// Trigger recording timer, only for meeting allowing recording
if (props.recordProp.record) {