Feat(meeting): minimise sequential user pick (#13831)
Updating random user picker to reduce the probability that the exact same viewers would be selected first in successive random-pick runs
This commit is contained in:
parent
1a89f66c0e
commit
0bc62f66f4
@ -50,6 +50,8 @@ trait SystemConfiguration {
|
||||
lazy val endMeetingWhenNoMoreAuthedUsers = Try(config.getBoolean("apps.endMeetingWhenNoMoreAuthedUsers")).getOrElse(false)
|
||||
lazy val endMeetingWhenNoMoreAuthedUsersAfterMinutes = Try(config.getInt("apps.endMeetingWhenNoMoreAuthedUsersAfterMinutes")).getOrElse(2)
|
||||
|
||||
lazy val reduceDuplicatedPick = Try(config.getBoolean("apps.reduceDuplicatedPick")).getOrElse(false)
|
||||
|
||||
// Redis server configuration
|
||||
lazy val redisHost = Try(config.getString("redis.host")).getOrElse("127.0.0.1")
|
||||
lazy val redisPort = Try(config.getInt("redis.port")).getOrElse(6379)
|
||||
|
@ -5,6 +5,7 @@ import org.bigbluebutton.core.running.{ LiveMeeting, OutMsgRouter }
|
||||
import org.bigbluebutton.core.models.{ UserState, Users2x }
|
||||
import org.bigbluebutton.core.apps.{ PermissionCheck, RightsManagementTrait }
|
||||
import org.bigbluebutton.core2.MeetingStatus2x
|
||||
import org.bigbluebutton.SystemConfiguration
|
||||
import scala.util.Random
|
||||
|
||||
trait SelectRandomViewerReqMsgHdlr extends RightsManagementTrait {
|
||||
@ -15,7 +16,7 @@ trait SelectRandomViewerReqMsgHdlr extends RightsManagementTrait {
|
||||
def handleSelectRandomViewerReqMsg(msg: SelectRandomViewerReqMsg): Unit = {
|
||||
log.debug("Received SelectRandomViewerReqMsg {}", SelectRandomViewerReqMsg)
|
||||
|
||||
def broadcastEvent(msg: SelectRandomViewerReqMsg, users: Vector[String], choice: Integer): Unit = {
|
||||
def broadcastEvent(msg: SelectRandomViewerReqMsg, users: Vector[String], choice: String): Unit = {
|
||||
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, liveMeeting.props.meetingProp.intId, msg.header.userId)
|
||||
val envelope = BbbCoreEnvelope(SelectRandomViewerRespMsg.NAME, routing)
|
||||
val header = BbbClientMsgHeader(SelectRandomViewerRespMsg.NAME, liveMeeting.props.meetingProp.intId, msg.header.userId)
|
||||
@ -31,11 +32,27 @@ trait SelectRandomViewerReqMsgHdlr extends RightsManagementTrait {
|
||||
val reason = "No permission to select random user."
|
||||
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, outGW, liveMeeting)
|
||||
} else {
|
||||
val users = Users2x.findNotPresentersNorModerators(liveMeeting.users2x)
|
||||
val randNum = new scala.util.Random
|
||||
val users = Users2x.getRandomlyPickableUsers(liveMeeting.users2x, false)
|
||||
|
||||
val usersPicked = Users2x.getRandomlyPickableUsers(liveMeeting.users2x, reduceDuplicatedPick)
|
||||
|
||||
val randNum = new scala.util.Random
|
||||
val pickedUser = if (usersPicked.size == 0) "" else usersPicked(randNum.nextInt(usersPicked.size)).intId
|
||||
|
||||
if (reduceDuplicatedPick) {
|
||||
if (usersPicked.size == 1) {
|
||||
// Initialise the exemption
|
||||
val usersToUnexempt = Users2x.findAll(liveMeeting.users2x)
|
||||
usersToUnexempt foreach { u =>
|
||||
Users2x.setUserExempted(liveMeeting.users2x, u.intId, false)
|
||||
}
|
||||
} else if (usersPicked.size > 1) {
|
||||
Users2x.setUserExempted(liveMeeting.users2x, pickedUser, true)
|
||||
}
|
||||
}
|
||||
|
||||
val userIds = users.map { case (v) => v.intId }
|
||||
broadcastEvent(msg, userIds, if (users.size == 0) -1 else randNum.nextInt(users.size))
|
||||
broadcastEvent(msg, userIds, pickedUser)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -71,8 +71,13 @@ object Users2x {
|
||||
users.toVector.filter(u => !u.presenter)
|
||||
}
|
||||
|
||||
def findNotPresentersNorModerators(users: Users2x): Vector[UserState] = {
|
||||
users.toVector.filter(u => !u.presenter && u.role != Roles.MODERATOR_ROLE)
|
||||
def getRandomlyPickableUsers(users: Users2x, reduceDup: Boolean): Vector[UserState] = {
|
||||
|
||||
if (reduceDup) {
|
||||
users.toVector.filter(u => !u.presenter && u.role != Roles.MODERATOR_ROLE && !u.userLeftFlag.left && !u.pickExempted)
|
||||
} else {
|
||||
users.toVector.filter(u => !u.presenter && u.role != Roles.MODERATOR_ROLE && !u.userLeftFlag.left)
|
||||
}
|
||||
}
|
||||
|
||||
def findViewers(users: Users2x): Vector[UserState] = {
|
||||
@ -150,6 +155,16 @@ object Users2x {
|
||||
}
|
||||
}
|
||||
|
||||
def setUserExempted(users: Users2x, intId: String, exempted: Boolean): Option[UserState] = {
|
||||
for {
|
||||
u <- findWithIntId(users, intId)
|
||||
} yield {
|
||||
val newUser = u.modify(_.pickExempted).setTo(exempted)
|
||||
users.save(newUser)
|
||||
newUser
|
||||
}
|
||||
}
|
||||
|
||||
def hasPresenter(users: Users2x): Boolean = {
|
||||
findPresenter(users) match {
|
||||
case Some(p) => true
|
||||
@ -294,6 +309,7 @@ case class UserState(
|
||||
lastActivityTime: Long = System.currentTimeMillis(),
|
||||
lastInactivityInspect: Long = 0,
|
||||
clientType: String,
|
||||
pickExempted: Boolean,
|
||||
userLeftFlag: UserLeftFlag
|
||||
)
|
||||
|
||||
|
@ -64,6 +64,7 @@ trait HandlerHelpers extends SystemConfiguration {
|
||||
locked = MeetingStatus2x.getPermissions(liveMeeting.status).lockOnJoin,
|
||||
avatar = regUser.avatarURL,
|
||||
clientType = clientType,
|
||||
pickExempted = false,
|
||||
userLeftFlag = UserLeftFlag(false, 0)
|
||||
)
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ trait FakeTestData {
|
||||
UserState(intId = regUser.id, extId = regUser.externId, name = regUser.name, role = regUser.role,
|
||||
guest = regUser.guest, authed = regUser.authed, guestStatus = regUser.guestStatus,
|
||||
emoji = "none", locked = false, presenter = false, avatar = regUser.avatarURL, clientType = "unknown",
|
||||
userLeftFlag = UserLeftFlag(false, 0))
|
||||
pickExempted = false, userLeftFlag = UserLeftFlag(false, 0))
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -76,6 +76,7 @@ apps {
|
||||
ejectOnViolation = false
|
||||
endMeetingWhenNoMoreAuthedUsers = false
|
||||
endMeetingWhenNoMoreAuthedUsersAfterMinutes = 2
|
||||
reduceDuplicatedPick = false
|
||||
}
|
||||
|
||||
analytics {
|
||||
|
@ -409,4 +409,4 @@ case class SelectRandomViewerReqMsgBody(requestedBy: String)
|
||||
*/
|
||||
object SelectRandomViewerRespMsg { val NAME = "SelectRandomViewerRespMsg" }
|
||||
case class SelectRandomViewerRespMsg(header: BbbClientMsgHeader, body: SelectRandomViewerRespMsgBody) extends StandardMsg
|
||||
case class SelectRandomViewerRespMsgBody(requestedBy: String, userIds: Vector[String], choice: Integer)
|
||||
case class SelectRandomViewerRespMsgBody(requestedBy: String, userIds: Vector[String], choice: String)
|
||||
|
@ -8,7 +8,7 @@ export default function randomlySelectedUser({ header, body }) {
|
||||
check(meetingId, String);
|
||||
check(requestedBy, String);
|
||||
check(userIds, Array);
|
||||
check(choice, Number);
|
||||
check(choice, String);
|
||||
|
||||
updateRandomViewer(meetingId, userIds, choice, requestedBy);
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ import { check } from 'meteor/check';
|
||||
export default function updateRandomUser(meetingId, userIds, choice, requesterId) {
|
||||
check(meetingId, String);
|
||||
check(userIds, Array);
|
||||
check(choice, Number);
|
||||
check(choice, String);
|
||||
check(requesterId, String);
|
||||
|
||||
const selector = {
|
||||
@ -13,7 +13,7 @@ export default function updateRandomUser(meetingId, userIds, choice, requesterId
|
||||
};
|
||||
|
||||
const userList = [];
|
||||
if (choice < 0) { // no viewer
|
||||
if (choice == "") { // no viewer
|
||||
userList.push([requesterId,0]);
|
||||
} else if (userIds.length == 1) {
|
||||
userList.push([userIds[0],0]);
|
||||
@ -26,7 +26,7 @@ export default function updateRandomUser(meetingId, userIds, choice, requesterId
|
||||
}
|
||||
userList.push([userId, intervals.shift()]);
|
||||
}
|
||||
userList[userList.length-1][0] = userIds[choice]; // last one should be chosen in akka-app
|
||||
userList[userList.length-1][0] = choice; // last one should be chosen in akka-app
|
||||
}
|
||||
|
||||
if (userIds.length == 2) {
|
||||
|
@ -126,7 +126,8 @@ class RandomUserSelect extends Component {
|
||||
const counter = SELECT_RANDOM_USER_COUNTDOWN ? this.state.count : 0;
|
||||
if (mappedRandomlySelectedUsers.length < counter + 1) return null;
|
||||
|
||||
const selectedUser = mappedRandomlySelectedUsers[counter][0];
|
||||
const selectedUser = SELECT_RANDOM_USER_COUNTDOWN ? mappedRandomlySelectedUsers[counter][0] :
|
||||
mappedRandomlySelectedUsers[mappedRandomlySelectedUsers.length - 1][0];
|
||||
const countDown = SELECT_RANDOM_USER_COUNTDOWN ?
|
||||
mappedRandomlySelectedUsers.length - this.state.count - 1 : 0;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user