openvidu-test-e2e: mediaServerReconnect tests
This commit is contained in:
parent
82115a7ce8
commit
9b599ebb6a
@ -21,18 +21,18 @@ public enum EndReason {
|
||||
|
||||
/**
|
||||
* A user called the RPC operation to unsubscribe from a remote stream. Applies
|
||||
* to webrtcConnectionDestroyed
|
||||
* to event webrtcConnectionDestroyed
|
||||
*/
|
||||
unsubscribe,
|
||||
|
||||
/**
|
||||
* A user called the RPC operation to unpublish a local stream. Applies to
|
||||
* A user called the RPC operation to unpublish a local stream. Applies to event
|
||||
* webrtcConnectionDestroyed
|
||||
*/
|
||||
unpublish,
|
||||
|
||||
/**
|
||||
* A user called the RPC operation to leave the session. Applies to
|
||||
* A user called the RPC operation to leave the session. Applies to events
|
||||
* webrtcConnectionDestroyed and participantLeft. Can trigger other events with
|
||||
* lastParticipantLeft
|
||||
*/
|
||||
@ -40,49 +40,49 @@ public enum EndReason {
|
||||
|
||||
/**
|
||||
* A user called the RPC operation to force the unpublishing of a remote stream.
|
||||
* Applies to webrtcConnectionDestroyed
|
||||
* Applies to event webrtcConnectionDestroyed
|
||||
*/
|
||||
forceUnpublishByUser,
|
||||
|
||||
/**
|
||||
* The server application called the REST operation to force the unpublishing of
|
||||
* a user's stream. Applies to webrtcConnectionDestroyed
|
||||
* a user's stream. Applies to event webrtcConnectionDestroyed
|
||||
*/
|
||||
forceUnpublishByServer,
|
||||
|
||||
/**
|
||||
* A user called the RPC operation to force the disconnection of a remote user.
|
||||
* Applies to webrtcConnectionDestroyed and participantLeft. Can trigger other
|
||||
* events with lastParticipantLeft
|
||||
* Applies to events webrtcConnectionDestroyed and participantLeft. Can trigger
|
||||
* other events with lastParticipantLeft
|
||||
*/
|
||||
forceDisconnectByUser,
|
||||
|
||||
/**
|
||||
* The server application called the REST operation to force the disconnection
|
||||
* of a user. Applies to webrtcConnectionDestroyed and participantLeft. Can
|
||||
* trigger other events with lastParticipantLeft
|
||||
* of a user. Applies to events webrtcConnectionDestroyed and participantLeft.
|
||||
* Can trigger other events with lastParticipantLeft
|
||||
*/
|
||||
forceDisconnectByServer,
|
||||
|
||||
/**
|
||||
* The last participant left the session, which caused the session to be closed.
|
||||
* Applies to webrtcConnectionDestroyed, participantLeft, recordingStatusChanged
|
||||
* and sessionDestroyed. Can be triggered from other events with other end
|
||||
* reasons (disconnect, forceDisconnectByUser, forceDisconnectByServer,
|
||||
* networkDisconnect)
|
||||
* Applies to events webrtcConnectionDestroyed, participantLeft,
|
||||
* recordingStatusChanged and sessionDestroyed. Can be triggered from other
|
||||
* events with other end reasons (disconnect, forceDisconnectByUser,
|
||||
* forceDisconnectByServer, networkDisconnect)
|
||||
*/
|
||||
lastParticipantLeft,
|
||||
|
||||
/**
|
||||
* The server application called the REST operation to stop a recording. Applies
|
||||
* to recordingStatusChanged
|
||||
* to event recordingStatusChanged
|
||||
*/
|
||||
recordingStoppedByServer,
|
||||
|
||||
/**
|
||||
* The server application called the REST operation to close a session. Applies
|
||||
* to webrtcConnectionDestroyed, participantLeft, recordingStatusChanged and
|
||||
* sessionDestroyed
|
||||
* to events webrtcConnectionDestroyed, participantLeft, recordingStatusChanged
|
||||
* and sessionDestroyed
|
||||
*/
|
||||
sessionClosedByServer,
|
||||
|
||||
@ -95,7 +95,7 @@ public enum EndReason {
|
||||
|
||||
/**
|
||||
* A media server disconnected. This is reserved for Media Nodes being
|
||||
* gracefully removed from an OpenVidu Pro cluster. Applies to
|
||||
* gracefully removed from an OpenVidu Pro cluster. Applies to events
|
||||
* webrtcConnectionDestroyed, participantLeft, recordingStatusChanged and
|
||||
* sessionDestroyed
|
||||
*/
|
||||
@ -103,29 +103,29 @@ public enum EndReason {
|
||||
|
||||
/**
|
||||
* A media server disconnected, and a new one automatically reconnected. All of
|
||||
* the media endpoints were destroyed in the process. Applies to
|
||||
* the media endpoints were destroyed in the process. Applies to events
|
||||
* webrtcConnectionDestroyed and recordingStatusChanged
|
||||
*/
|
||||
mediaServerReconnect,
|
||||
|
||||
/**
|
||||
* A node has crashed. For now this means a Media Node has crashed. Applies to
|
||||
* webrtcConnectionDestroyed, participantLeft, recordingStatusChanged and
|
||||
* events webrtcConnectionDestroyed, participantLeft, recordingStatusChanged and
|
||||
* sessionDestroyed
|
||||
*/
|
||||
nodeCrashed,
|
||||
|
||||
/**
|
||||
* OpenVidu Server has gracefully stopped. This is reserved for OpenVidu Pro
|
||||
* restart operation. Applies to webrtcConnectionDestroyed, participantLeft,
|
||||
* recordingStatusChanged and sessionDestroyed
|
||||
* restart operation. Applies to events webrtcConnectionDestroyed,
|
||||
* participantLeft, recordingStatusChanged and sessionDestroyed
|
||||
*/
|
||||
openviduServerStopped,
|
||||
|
||||
/**
|
||||
* A recording has been stopped automatically
|
||||
* (https://docs.openvidu.io/en/stable/advanced-features/recording/#automatic-stop-of-recordings).
|
||||
* Applies to recordingStatusChanged
|
||||
* Applies to event recordingStatusChanged
|
||||
*/
|
||||
automaticStop
|
||||
|
||||
|
||||
@ -246,6 +246,15 @@ public class KurentoSession extends Session {
|
||||
}
|
||||
}
|
||||
|
||||
private void resetPipeline(Runnable callback) {
|
||||
pipeline = null;
|
||||
pipelineLatch = new CountDownLatch(1);
|
||||
pipelineCreationErrorCause = null;
|
||||
if (callback != null) {
|
||||
callback.run();
|
||||
}
|
||||
}
|
||||
|
||||
private void closePipeline(Runnable callback) {
|
||||
synchronized (pipelineReleaseLock) {
|
||||
if (pipeline == null) {
|
||||
@ -260,25 +269,17 @@ public class KurentoSession extends Session {
|
||||
@Override
|
||||
public void onSuccess(Void result) throws Exception {
|
||||
log.debug("SESSION {}: Released Pipeline", sessionId);
|
||||
pipeline = null;
|
||||
pipelineLatch = new CountDownLatch(1);
|
||||
pipelineCreationErrorCause = null;
|
||||
if (callback != null) {
|
||||
callback.run();
|
||||
}
|
||||
resetPipeline(callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable cause) throws Exception {
|
||||
log.warn("SESSION {}: Could not successfully release Pipeline", sessionId, cause);
|
||||
pipeline = null;
|
||||
pipelineLatch = new CountDownLatch(1);
|
||||
pipelineCreationErrorCause = null;
|
||||
if (callback != null) {
|
||||
callback.run();
|
||||
}
|
||||
resetPipeline(callback);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
resetPipeline(callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -330,27 +331,33 @@ public class KurentoSession extends Session {
|
||||
// Release pipeline, create a new one and prepare new PublisherEndpoints for
|
||||
// allowed users
|
||||
log.info("Resetting process: closing media pipeline for active session {}", this.sessionId);
|
||||
this.closePipeline(() -> {
|
||||
log.info("Resetting process: media pipeline closed for active session {}", this.sessionId);
|
||||
createPipeline();
|
||||
try {
|
||||
if (!pipelineLatch.await(20, TimeUnit.SECONDS)) {
|
||||
throw new Exception("MediaPipeline was not created in 20 seconds");
|
||||
}
|
||||
getParticipants().forEach(p -> {
|
||||
if (!OpenViduRole.SUBSCRIBER.equals(p.getToken().getRole())) {
|
||||
|
||||
((KurentoParticipant) p).resetPublisherEndpoint(mediaOptionsMap.get(p.getParticipantPublicId()),
|
||||
null);
|
||||
try {
|
||||
RemoteOperationUtils.setToSkipRemoteOperations();
|
||||
this.closePipeline(() -> {
|
||||
RemoteOperationUtils.revertToRunRemoteOperations();
|
||||
log.info("Resetting process: media pipeline closed for active session {}", this.sessionId);
|
||||
createPipeline();
|
||||
try {
|
||||
if (!pipelineLatch.await(20, TimeUnit.SECONDS)) {
|
||||
throw new Exception("MediaPipeline was not created in 20 seconds");
|
||||
}
|
||||
});
|
||||
log.info(
|
||||
"Resetting process: media pipeline created and publisher endpoints reseted for active session {}",
|
||||
this.sessionId);
|
||||
} catch (Exception e) {
|
||||
log.error("Error waiting to new MediaPipeline on KurentoSession restart: {}", e.getMessage());
|
||||
}
|
||||
});
|
||||
getParticipants().forEach(p -> {
|
||||
if (!OpenViduRole.SUBSCRIBER.equals(p.getToken().getRole())) {
|
||||
|
||||
((KurentoParticipant) p)
|
||||
.resetPublisherEndpoint(mediaOptionsMap.get(p.getParticipantPublicId()), null);
|
||||
}
|
||||
});
|
||||
log.info(
|
||||
"Resetting process: media pipeline created and publisher endpoints reseted for active session {}",
|
||||
this.sessionId);
|
||||
} catch (Exception e) {
|
||||
log.error("Error waiting to new MediaPipeline on KurentoSession restart: {}", e.getMessage());
|
||||
}
|
||||
});
|
||||
} finally {
|
||||
RemoteOperationUtils.revertToRunRemoteOperations();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -362,7 +362,6 @@ public class RecordingManager {
|
||||
}
|
||||
|
||||
((RecordingService) singleStreamRecordingService).sealRecordingMetadataFileAsStopped(recording);
|
||||
|
||||
final long timestamp = System.currentTimeMillis();
|
||||
this.cdr.recordRecordingStatusChanged(recording, reason, timestamp, Status.stopped);
|
||||
|
||||
@ -384,6 +383,11 @@ public class RecordingManager {
|
||||
public Recording forceStopRecording(Session session, EndReason reason, Long kmsDisconnectionTime) {
|
||||
Recording recording;
|
||||
recording = this.sessionsRecordings.get(session.getSessionId());
|
||||
|
||||
((RecordingService) singleStreamRecordingService).sealRecordingMetadataFileAsStopped(recording);
|
||||
final long timestamp = System.currentTimeMillis();
|
||||
this.cdr.recordRecordingStatusChanged(recording, reason, timestamp, Status.stopped);
|
||||
|
||||
switch (recording.getOutputMode()) {
|
||||
case COMPOSED:
|
||||
recording = this.composedRecordingService.stopRecording(session, recording, reason, kmsDisconnectionTime);
|
||||
|
||||
@ -253,12 +253,26 @@ public class AbstractOpenViduTestAppE2eTest {
|
||||
other.dispose();
|
||||
it.remove();
|
||||
}
|
||||
this.closeAllSessions(OV);
|
||||
if (isRecordingTest) {
|
||||
deleteAllRecordings(OV);
|
||||
isRecordingTest = false;
|
||||
}
|
||||
if (isKurentoRestartTest) {
|
||||
this.stopMediaServer(false);
|
||||
this.startMediaServer(true);
|
||||
isKurentoRestartTest = false;
|
||||
}
|
||||
OV = new OpenVidu(OPENVIDU_URL, OPENVIDU_SECRET);
|
||||
}
|
||||
|
||||
protected void closeAllSessions(OpenVidu client) {
|
||||
try {
|
||||
OV.fetch();
|
||||
client.fetch();
|
||||
} catch (OpenViduJavaClientException | OpenViduHttpException e1) {
|
||||
log.error("Error fetching sessions: {}", e1.getMessage());
|
||||
}
|
||||
OV.getActiveSessions().forEach(session -> {
|
||||
client.getActiveSessions().forEach(session -> {
|
||||
try {
|
||||
session.close();
|
||||
log.info("Session {} successfully closed", session.getSessionId());
|
||||
@ -268,20 +282,29 @@ public class AbstractOpenViduTestAppE2eTest {
|
||||
log.error("Error closing session: {}", e.getMessage());
|
||||
}
|
||||
});
|
||||
if (isRecordingTest) {
|
||||
removeAllRecordingContiners();
|
||||
try {
|
||||
FileUtils.cleanDirectory(new File("/opt/openvidu/recordings"));
|
||||
} catch (IOException e) {
|
||||
log.error(e.getMessage());
|
||||
}
|
||||
isRecordingTest = false;
|
||||
}
|
||||
|
||||
protected void deleteAllRecordings(OpenVidu client) {
|
||||
try {
|
||||
client.listRecordings().forEach(recording -> {
|
||||
try {
|
||||
client.deleteRecording(recording.getId());
|
||||
log.info("Recording {} successfully deleted", recording.getId());
|
||||
} catch (OpenViduJavaClientException e) {
|
||||
log.error("Error deleting recording: {}", e.getMessage());
|
||||
} catch (OpenViduHttpException e) {
|
||||
log.error("Error deleting recording: {}", e.getMessage());
|
||||
}
|
||||
});
|
||||
} catch (OpenViduJavaClientException | OpenViduHttpException e) {
|
||||
log.error("Error listing recordings: {}", e.getMessage());
|
||||
}
|
||||
if (isKurentoRestartTest) {
|
||||
this.restartMediaServer();
|
||||
isKurentoRestartTest = false;
|
||||
removeAllRecordingContiners();
|
||||
try {
|
||||
FileUtils.cleanDirectory(new File("/opt/openvidu/recordings"));
|
||||
} catch (IOException e) {
|
||||
log.error(e.getMessage());
|
||||
}
|
||||
OV = new OpenVidu(OPENVIDU_URL, OPENVIDU_SECRET);
|
||||
}
|
||||
|
||||
protected void listEmptyRecordings() {
|
||||
@ -318,7 +341,7 @@ public class AbstractOpenViduTestAppE2eTest {
|
||||
return "data:image/png;base64," + screenshotBase64;
|
||||
}
|
||||
|
||||
protected void startMediaServer() {
|
||||
protected void startMediaServer(boolean waitUntilKurentoClientReconnection) {
|
||||
String command = null;
|
||||
if (MEDIA_SERVER_IMAGE.startsWith(KURENTO_IMAGE)) {
|
||||
log.info("Starting kurento");
|
||||
@ -336,9 +359,16 @@ public class AbstractOpenViduTestAppE2eTest {
|
||||
System.exit(1);
|
||||
}
|
||||
commandLine.executeCommand(command);
|
||||
if (waitUntilKurentoClientReconnection) {
|
||||
try {
|
||||
Thread.sleep(4000);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void stopMediaServer() {
|
||||
protected void stopMediaServer(boolean waitUntilNodeCrashedEvent) {
|
||||
final String dockerRemoveCmd = "docker ps -a | awk '{ print $1,$2 }' | grep GREP_PARAMETER | awk '{ print $1 }' | xargs -I {} docker rm -f {}";
|
||||
String grep = null;
|
||||
if (MEDIA_SERVER_IMAGE.startsWith(KURENTO_IMAGE)) {
|
||||
@ -352,17 +382,13 @@ public class AbstractOpenViduTestAppE2eTest {
|
||||
System.exit(1);
|
||||
}
|
||||
commandLine.executeCommand(dockerRemoveCmd.replaceFirst("GREP_PARAMETER", grep));
|
||||
}
|
||||
|
||||
protected void restartMediaServer() {
|
||||
this.stopMediaServer();
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException e) {
|
||||
System.err.println("Error restarting media server");
|
||||
e.printStackTrace();
|
||||
if (waitUntilNodeCrashedEvent) {
|
||||
try {
|
||||
Thread.sleep(4000);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
this.startMediaServer();
|
||||
}
|
||||
|
||||
protected void checkDockerContainerRunning(String imageName, int amount) {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user