public async Task JoinRoom_DoNothing_HasSceneStack() { // arrange await Mediator.Send(new OpenConferenceRequest(ConferenceId)); // act await JoinParticipant(TestData.Sven); // assert var scenes = SynchronizedObjectListener.GetSynchronizedObject <SynchronizedScene>(TestData.Sven.Participant, SynchronizedScene.SyncObjId(DefaultRoomId)); Assert.Equal(SynchronizedSceneProvider.GetDefaultScene(), scenes.SelectedScene); Assert.Equal(DefaultSceneStack, scenes.SceneStack); Assert.Null(scenes.OverwrittenContent); Assert.NotNull(scenes.AvailableScenes); }
private async Task ApplyScene(string conferenceId, string roomId, ActiveScene scene, SceneState currentState) { var sceneState = await CreateNewSceneState(conferenceId, roomId, scene, currentState); await _sceneRepository.SetSceneState(conferenceId, roomId, sceneState); // optimistic concurrency // very important, we need to know the current state AFTER we saved the new state in repository await _mediator.Send(new ClearCacheRequest()); var availableScenes = await _mediator.Send(new FetchAvailableScenesRequest(conferenceId, roomId, sceneState.SceneStack)); if (!VerifySceneState(sceneState, availableScenes)) { // something wrong with the applied scenes, we have to adjust here if (scene.OverwrittenContent != null && !availableScenes.Contains(scene.OverwrittenContent)) { scene = scene with { OverwrittenContent = null }; } if (!availableScenes.Contains(scene.SelectedScene)) { scene = scene with { SelectedScene = scene.OverwrittenContent ?? SynchronizedSceneProvider.GetDefaultScene(), OverwrittenContent = null, }; } if (_recursionCounter++ > 10) { var safeSceneStack = sceneState.SceneStack.TakeWhile(availableScenes.Contains).ToList(); await _sceneRepository.SetSceneState(conferenceId, roomId, sceneState with { SceneStack = safeSceneStack });
public async Task <Unit> Handle(UpdateScenesRequest request, CancellationToken cancellationToken) { var(conferenceId, roomId) = request; await using (await _sceneRepository.LockScene(conferenceId, roomId)) { var scene = await _sceneRepository.GetScene(conferenceId, roomId); scene ??= SynchronizedSceneProvider.GetDefaultActiveScene(); var state = await _sceneRepository.GetSceneState(conferenceId, roomId); state ??= SynchronizedSceneProvider.GetEmptySceneState(); await ApplyScene(conferenceId, roomId, scene, state); } await _mediator.Send( new UpdateSynchronizedObjectRequest(conferenceId, SynchronizedScene.SyncObjId(roomId))); return(Unit.Value); }
public async ValueTask Handle(string conferenceId, string roomId, Func <ActiveScene, ActiveScene> patchFunc) { await using (await _sceneRepository.LockScene(conferenceId, roomId)) { var previousScene = await _sceneRepository.GetScene(conferenceId, roomId); previousScene ??= SynchronizedSceneProvider.GetDefaultActiveScene(); await _sceneRepository.SetScene(conferenceId, roomId, patchFunc(previousScene)); } // for optimistic concurrency await _mediator.Send(new ClearCacheRequest()); if (!await IsRoomExisting(conferenceId, roomId)) { await _sceneRepository.RemoveScene(conferenceId, roomId); throw SceneError.RoomNotFound.ToException(); } await _mediator.Send(new UpdateScenesRequest(conferenceId, roomId)); }