mirror of https://github.com/OpenVidu/openvidu.git
openvidu-server: skip Kurento remote operations if node crashed
parent
63b312227f
commit
f6422c7a40
|
@ -58,6 +58,7 @@ import io.openvidu.server.kurento.endpoint.MediaEndpoint;
|
||||||
import io.openvidu.server.kurento.endpoint.PublisherEndpoint;
|
import io.openvidu.server.kurento.endpoint.PublisherEndpoint;
|
||||||
import io.openvidu.server.kurento.endpoint.SubscriberEndpoint;
|
import io.openvidu.server.kurento.endpoint.SubscriberEndpoint;
|
||||||
import io.openvidu.server.recording.service.RecordingManager;
|
import io.openvidu.server.recording.service.RecordingManager;
|
||||||
|
import io.openvidu.server.utils.RemoteOperationUtils;
|
||||||
|
|
||||||
public class KurentoParticipant extends Participant {
|
public class KurentoParticipant extends Participant {
|
||||||
|
|
||||||
|
@ -663,7 +664,9 @@ public class KurentoParticipant extends Participant {
|
||||||
senderPublisher.numberOfSubscribers--;
|
senderPublisher.numberOfSubscribers--;
|
||||||
if (senderPublisher.isPlayerEndpoint() && senderPublisher.numberOfSubscribers == 0) {
|
if (senderPublisher.isPlayerEndpoint() && senderPublisher.numberOfSubscribers == 0) {
|
||||||
try {
|
try {
|
||||||
|
if (!RemoteOperationUtils.mustSkipRemoteOperation()) {
|
||||||
senderPublisher.getPlayerEndpoint().stop();
|
senderPublisher.getPlayerEndpoint().stop();
|
||||||
|
}
|
||||||
log.info(
|
log.info(
|
||||||
"IP Camera stream {} feed is now disabled because there are no subscribers",
|
"IP Camera stream {} feed is now disabled because there are no subscribers",
|
||||||
senderPublisher.getStreamId());
|
senderPublisher.getStreamId());
|
||||||
|
@ -691,6 +694,7 @@ public class KurentoParticipant extends Participant {
|
||||||
void releaseElement(final String senderName, final MediaElement element) {
|
void releaseElement(final String senderName, final MediaElement element) {
|
||||||
final String eid = element.getId();
|
final String eid = element.getId();
|
||||||
try {
|
try {
|
||||||
|
if (!RemoteOperationUtils.mustSkipRemoteOperation()) {
|
||||||
element.release(new Continuation<Void>() {
|
element.release(new Continuation<Void>() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(Void result) throws Exception {
|
public void onSuccess(Void result) throws Exception {
|
||||||
|
@ -704,6 +708,7 @@ public class KurentoParticipant extends Participant {
|
||||||
eid, senderName, cause);
|
eid, senderName, cause);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("PARTICIPANT {}: Error calling release on elem #{} for {}", getParticipantPublicId(), eid,
|
log.error("PARTICIPANT {}: Error calling release on elem #{} for {}", getParticipantPublicId(), eid,
|
||||||
senderName, e);
|
senderName, e);
|
||||||
|
|
|
@ -42,6 +42,7 @@ import io.openvidu.server.core.MediaOptions;
|
||||||
import io.openvidu.server.core.Participant;
|
import io.openvidu.server.core.Participant;
|
||||||
import io.openvidu.server.core.Session;
|
import io.openvidu.server.core.Session;
|
||||||
import io.openvidu.server.kurento.kms.Kms;
|
import io.openvidu.server.kurento.kms.Kms;
|
||||||
|
import io.openvidu.server.utils.RemoteOperationUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Pablo Fuente (pablofuenteperez@gmail.com)
|
* @author Pablo Fuente (pablofuenteperez@gmail.com)
|
||||||
|
@ -252,6 +253,7 @@ public class KurentoSession extends Session {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!RemoteOperationUtils.mustSkipRemoteOperation()) {
|
||||||
getPipeline().release(new Continuation<Void>() {
|
getPipeline().release(new Continuation<Void>() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(Void result) throws Exception {
|
public void onSuccess(Void result) throws Exception {
|
||||||
|
@ -277,12 +279,13 @@ public class KurentoSession extends Session {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public String getParticipantPrivateIdFromStreamId(String streamId) {
|
public String getParticipantPrivateIdFromStreamId(String streamId) {
|
||||||
return this.publishedStreamIds.get(streamId);
|
return this.publishedStreamIds.get(streamId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void restartStatusInKurento(Long kmsDisconnectionTime) {
|
public void restartStatusInKurentoAfterReconnection(Long kmsDisconnectionTime) {
|
||||||
|
|
||||||
log.info("Resetting process: resetting remote media objects for active session {}", this.sessionId);
|
log.info("Resetting process: resetting remote media objects for active session {}", this.sessionId);
|
||||||
|
|
||||||
|
|
|
@ -63,6 +63,7 @@ import io.openvidu.server.config.OpenviduConfig;
|
||||||
import io.openvidu.server.core.Participant;
|
import io.openvidu.server.core.Participant;
|
||||||
import io.openvidu.server.kurento.core.KurentoMediaOptions;
|
import io.openvidu.server.kurento.core.KurentoMediaOptions;
|
||||||
import io.openvidu.server.kurento.core.KurentoParticipant;
|
import io.openvidu.server.kurento.core.KurentoParticipant;
|
||||||
|
import io.openvidu.server.utils.RemoteOperationUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link Endpoint} wrapper. Can be based on WebRtcEndpoint (that supports
|
* {@link Endpoint} wrapper. Can be based on WebRtcEndpoint (that supports
|
||||||
|
@ -471,8 +472,10 @@ public abstract class MediaEndpoint {
|
||||||
if (element == null || subscription == null) {
|
if (element == null || subscription == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (!RemoteOperationUtils.mustSkipRemoteOperation()) {
|
||||||
element.removeErrorListener(subscription);
|
element.removeErrorListener(subscription);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Orders the internal endpoint ({@link RtpEndpoint} or {@link WebRtcEndpoint})
|
* Orders the internal endpoint ({@link RtpEndpoint} or {@link WebRtcEndpoint})
|
||||||
|
|
|
@ -52,6 +52,7 @@ import io.openvidu.server.core.MediaOptions;
|
||||||
import io.openvidu.server.kurento.core.KurentoMediaOptions;
|
import io.openvidu.server.kurento.core.KurentoMediaOptions;
|
||||||
import io.openvidu.server.kurento.core.KurentoParticipant;
|
import io.openvidu.server.kurento.core.KurentoParticipant;
|
||||||
import io.openvidu.server.utils.JsonUtils;
|
import io.openvidu.server.utils.JsonUtils;
|
||||||
|
import io.openvidu.server.utils.RemoteOperationUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Publisher aspect of the {@link MediaEndpoint}.
|
* Publisher aspect of the {@link MediaEndpoint}.
|
||||||
|
@ -333,6 +334,7 @@ public class PublisherEndpoint extends MediaEndpoint {
|
||||||
}
|
}
|
||||||
elementIds.remove(elementId);
|
elementIds.remove(elementId);
|
||||||
if (releaseElement) {
|
if (releaseElement) {
|
||||||
|
if (!RemoteOperationUtils.mustSkipRemoteOperation()) {
|
||||||
element.release(new Continuation<Void>() {
|
element.release(new Continuation<Void>() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(Void result) throws Exception {
|
public void onSuccess(Void result) throws Exception {
|
||||||
|
@ -345,6 +347,7 @@ public class PublisherEndpoint extends MediaEndpoint {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
this.filter = null;
|
this.filter = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -504,6 +507,7 @@ public class PublisherEndpoint extends MediaEndpoint {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void internalSinkDisconnect(final MediaElement source, final MediaElement sink, boolean blocking) {
|
private void internalSinkDisconnect(final MediaElement source, final MediaElement sink, boolean blocking) {
|
||||||
|
if (!RemoteOperationUtils.mustSkipRemoteOperation()) {
|
||||||
if (blocking) {
|
if (blocking) {
|
||||||
source.disconnect(sink);
|
source.disconnect(sink);
|
||||||
} else {
|
} else {
|
||||||
|
@ -522,6 +526,7 @@ public class PublisherEndpoint extends MediaEndpoint {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Same as {@link #internalSinkDisconnect(MediaElement, MediaElement)}, but can
|
* Same as {@link #internalSinkDisconnect(MediaElement, MediaElement)}, but can
|
||||||
|
@ -536,6 +541,7 @@ public class PublisherEndpoint extends MediaEndpoint {
|
||||||
*/
|
*/
|
||||||
private void internalSinkDisconnect(final MediaElement source, final MediaElement sink, final MediaType type,
|
private void internalSinkDisconnect(final MediaElement source, final MediaElement sink, final MediaType type,
|
||||||
boolean blocking) {
|
boolean blocking) {
|
||||||
|
if (!RemoteOperationUtils.mustSkipRemoteOperation()) {
|
||||||
if (type == null) {
|
if (type == null) {
|
||||||
internalSinkDisconnect(source, sink, blocking);
|
internalSinkDisconnect(source, sink, blocking);
|
||||||
} else {
|
} else {
|
||||||
|
@ -558,6 +564,7 @@ public class PublisherEndpoint extends MediaEndpoint {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public MediaOptions getMediaOptions() {
|
public MediaOptions getMediaOptions() {
|
||||||
return mediaOptions;
|
return mediaOptions;
|
||||||
|
|
|
@ -51,6 +51,7 @@ import io.openvidu.server.core.SessionManager;
|
||||||
import io.openvidu.server.kurento.core.KurentoSession;
|
import io.openvidu.server.kurento.core.KurentoSession;
|
||||||
import io.openvidu.server.utils.MediaNodeStatusManager;
|
import io.openvidu.server.utils.MediaNodeStatusManager;
|
||||||
import io.openvidu.server.utils.QuarantineKiller;
|
import io.openvidu.server.utils.QuarantineKiller;
|
||||||
|
import io.openvidu.server.utils.RemoteOperationUtils;
|
||||||
import io.openvidu.server.utils.UpdatableTimerTask;
|
import io.openvidu.server.utils.UpdatableTimerTask;
|
||||||
|
|
||||||
public abstract class KmsManager {
|
public abstract class KmsManager {
|
||||||
|
@ -227,7 +228,14 @@ public abstract class KmsManager {
|
||||||
log.warn("Closing {} sessions hosted by KMS with uri {}: {}", kms.getKurentoSessions().size(),
|
log.warn("Closing {} sessions hosted by KMS with uri {}: {}", kms.getKurentoSessions().size(),
|
||||||
kms.getUri(), kms.getKurentoSessions().stream().map(s -> s.getSessionId())
|
kms.getUri(), kms.getKurentoSessions().stream().map(s -> s.getSessionId())
|
||||||
.collect(Collectors.joining(",", "[", "]")));
|
.collect(Collectors.joining(",", "[", "]")));
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Flag the thread to skip remote operations to KMS
|
||||||
|
RemoteOperationUtils.setToSkipRemoteOperations();
|
||||||
sessionManager.closeAllSessionsAndRecordingsOfKms(kms, EndReason.nodeCrashed);
|
sessionManager.closeAllSessionsAndRecordingsOfKms(kms, EndReason.nodeCrashed);
|
||||||
|
} finally {
|
||||||
|
RemoteOperationUtils.revertToRunRemoteOperations();
|
||||||
|
}
|
||||||
|
|
||||||
// Remove Media Node
|
// Remove Media Node
|
||||||
log.warn("Removing Media Node {} after crash", kms.getId());
|
log.warn("Removing Media Node {} after crash", kms.getId());
|
||||||
|
@ -269,7 +277,7 @@ public abstract class KmsManager {
|
||||||
kms.getUri(), kms.getKurentoSessions().size(), kms.getKurentoSessions().stream()
|
kms.getUri(), kms.getKurentoSessions().size(), kms.getKurentoSessions().stream()
|
||||||
.map(s -> s.getSessionId()).collect(Collectors.joining(",", "[", "]")));
|
.map(s -> s.getSessionId()).collect(Collectors.joining(",", "[", "]")));
|
||||||
kms.getKurentoSessions().forEach(kSession -> {
|
kms.getKurentoSessions().forEach(kSession -> {
|
||||||
kSession.restartStatusInKurento(timeOfKurentoDisconnection);
|
kSession.restartStatusInKurentoAfterReconnection(timeOfKurentoDisconnection);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
log.info("KMS with URI {} is the same process. Nothing must be done", kms.getUri());
|
log.info("KMS with URI {} is the same process. Nothing must be done", kms.getUri());
|
||||||
|
|
|
@ -38,6 +38,7 @@ import io.openvidu.client.OpenViduException;
|
||||||
import io.openvidu.client.OpenViduException.Code;
|
import io.openvidu.client.OpenViduException.Code;
|
||||||
import io.openvidu.server.kurento.core.KurentoSession;
|
import io.openvidu.server.kurento.core.KurentoSession;
|
||||||
import io.openvidu.server.kurento.endpoint.PublisherEndpoint;
|
import io.openvidu.server.kurento.endpoint.PublisherEndpoint;
|
||||||
|
import io.openvidu.server.utils.RemoteOperationUtils;
|
||||||
|
|
||||||
public class CompositeWrapper {
|
public class CompositeWrapper {
|
||||||
|
|
||||||
|
@ -87,7 +88,21 @@ public class CompositeWrapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void stopCompositeRecording(CountDownLatch stopLatch, Long kmsDisconnectionTime) {
|
public synchronized void stopCompositeRecording(CountDownLatch stopLatch, Long kmsDisconnectionTime) {
|
||||||
if (kmsDisconnectionTime == null) {
|
|
||||||
|
if (kmsDisconnectionTime != null || RemoteOperationUtils.mustSkipRemoteOperation()) {
|
||||||
|
// Stopping composite endpoint because of a KMS disconnection
|
||||||
|
String msg;
|
||||||
|
if (kmsDisconnectionTime != null) {
|
||||||
|
endTime = kmsDisconnectionTime;
|
||||||
|
msg = "KMS restart";
|
||||||
|
} else {
|
||||||
|
endTime = System.currentTimeMillis();
|
||||||
|
msg = "node crashed";
|
||||||
|
}
|
||||||
|
stopLatch.countDown();
|
||||||
|
log.warn("Forcing composed audio-only recording stop after {} in session {}", msg,
|
||||||
|
this.session.getSessionId());
|
||||||
|
} else {
|
||||||
this.recorderEndpoint.addStoppedListener(new EventListener<StoppedEvent>() {
|
this.recorderEndpoint.addStoppedListener(new EventListener<StoppedEvent>() {
|
||||||
@Override
|
@Override
|
||||||
public void onEvent(StoppedEvent event) {
|
public void onEvent(StoppedEvent event) {
|
||||||
|
@ -100,11 +115,6 @@ public class CompositeWrapper {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.recorderEndpoint.stop();
|
this.recorderEndpoint.stop();
|
||||||
} else {
|
|
||||||
endTime = kmsDisconnectionTime;
|
|
||||||
stopLatch.countDown();
|
|
||||||
log.warn("Forcing composed audio-only recording stop after KMS restart in session {}",
|
|
||||||
this.session.getSessionId());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -145,7 +155,9 @@ public class CompositeWrapper {
|
||||||
HubPort hubPort = this.hubPorts.remove(streamId);
|
HubPort hubPort = this.hubPorts.remove(streamId);
|
||||||
PublisherEndpoint publisherEndpoint = this.publisherEndpoints.remove(streamId);
|
PublisherEndpoint publisherEndpoint = this.publisherEndpoints.remove(streamId);
|
||||||
publisherEndpoint.disconnectFrom(hubPort);
|
publisherEndpoint.disconnectFrom(hubPort);
|
||||||
|
if (!RemoteOperationUtils.mustSkipRemoteOperation()) {
|
||||||
hubPort.release();
|
hubPort.release();
|
||||||
|
}
|
||||||
log.info("Composite for session {} has now {} connected publishers", this.session.getSessionId(),
|
log.info("Composite for session {} has now {} connected publishers", this.session.getSessionId(),
|
||||||
this.composite.getChildren().size() - 1);
|
this.composite.getChildren().size() - 1);
|
||||||
}
|
}
|
||||||
|
@ -155,12 +167,16 @@ public class CompositeWrapper {
|
||||||
PublisherEndpoint endpoint = this.publisherEndpoints.get(streamId);
|
PublisherEndpoint endpoint = this.publisherEndpoints.get(streamId);
|
||||||
HubPort hubPort = this.hubPorts.get(streamId);
|
HubPort hubPort = this.hubPorts.get(streamId);
|
||||||
endpoint.disconnectFrom(hubPort);
|
endpoint.disconnectFrom(hubPort);
|
||||||
|
if (!RemoteOperationUtils.mustSkipRemoteOperation()) {
|
||||||
hubPort.release();
|
hubPort.release();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
this.hubPorts.clear();
|
this.hubPorts.clear();
|
||||||
this.publisherEndpoints.clear();
|
this.publisherEndpoints.clear();
|
||||||
|
if (!RemoteOperationUtils.mustSkipRemoteOperation()) {
|
||||||
this.composite.release();
|
this.composite.release();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public long getDuration() {
|
public long getDuration() {
|
||||||
return this.endTime - this.startTime;
|
return this.endTime - this.startTime;
|
||||||
|
|
|
@ -31,8 +31,9 @@ import java.util.NoSuchElementException;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
import java.util.concurrent.ScheduledFuture;
|
import java.util.concurrent.ScheduledFuture;
|
||||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
@ -79,6 +80,7 @@ import io.openvidu.server.utils.JsonUtils;
|
||||||
import io.openvidu.server.utils.LocalCustomFileManager;
|
import io.openvidu.server.utils.LocalCustomFileManager;
|
||||||
import io.openvidu.server.utils.LocalDockerManager;
|
import io.openvidu.server.utils.LocalDockerManager;
|
||||||
import io.openvidu.server.utils.RecordingUtils;
|
import io.openvidu.server.utils.RecordingUtils;
|
||||||
|
import io.openvidu.server.utils.RemoteOperationUtils;
|
||||||
|
|
||||||
public class RecordingManager {
|
public class RecordingManager {
|
||||||
|
|
||||||
|
@ -122,8 +124,8 @@ public class RecordingManager {
|
||||||
|
|
||||||
private JsonUtils jsonUtils = new JsonUtils();
|
private JsonUtils jsonUtils = new JsonUtils();
|
||||||
|
|
||||||
private ScheduledThreadPoolExecutor automaticRecordingStopExecutor = new ScheduledThreadPoolExecutor(
|
private ScheduledExecutorService automaticRecordingStopExecutor = Executors
|
||||||
Runtime.getRuntime().availableProcessors());
|
.newScheduledThreadPool(Runtime.getRuntime().availableProcessors());
|
||||||
|
|
||||||
public static final String IMAGE_NAME = "openvidu/openvidu-recording";
|
public static final String IMAGE_NAME = "openvidu/openvidu-recording";
|
||||||
|
|
||||||
|
@ -809,9 +811,11 @@ public class RecordingManager {
|
||||||
throw new OpenViduException(Code.RECORDING_PATH_NOT_VALID, errorMessage);
|
throw new OpenViduException(Code.RECORDING_PATH_NOT_VALID, errorMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!RemoteOperationUtils.mustSkipRemoteOperation()) {
|
||||||
recorder.stop();
|
recorder.stop();
|
||||||
recorder.release();
|
recorder.release();
|
||||||
pipeline.release();
|
pipeline.release();
|
||||||
|
}
|
||||||
|
|
||||||
log.info("Kurento Media Server has write permissions on recording path: {}", openviduRecordingPath);
|
log.info("Kurento Media Server has write permissions on recording path: {}", openviduRecordingPath);
|
||||||
|
|
||||||
|
|
|
@ -68,6 +68,7 @@ import io.openvidu.server.recording.Recording;
|
||||||
import io.openvidu.server.recording.RecordingDownloader;
|
import io.openvidu.server.recording.RecordingDownloader;
|
||||||
import io.openvidu.server.recording.RecordingUploader;
|
import io.openvidu.server.recording.RecordingUploader;
|
||||||
import io.openvidu.server.utils.CustomFileManager;
|
import io.openvidu.server.utils.CustomFileManager;
|
||||||
|
import io.openvidu.server.utils.RemoteOperationUtils;
|
||||||
|
|
||||||
public class SingleStreamRecordingService extends RecordingService {
|
public class SingleStreamRecordingService extends RecordingService {
|
||||||
|
|
||||||
|
@ -289,7 +290,20 @@ public class SingleStreamRecordingService extends RecordingService {
|
||||||
try {
|
try {
|
||||||
if (kParticipant.singleRecordingLock.tryLock(15, TimeUnit.SECONDS)) {
|
if (kParticipant.singleRecordingLock.tryLock(15, TimeUnit.SECONDS)) {
|
||||||
try {
|
try {
|
||||||
if (kmsDisconnectionTime == null) {
|
|
||||||
|
if (kmsDisconnectionTime != null || RemoteOperationUtils.mustSkipRemoteOperation()) {
|
||||||
|
|
||||||
|
// Stopping recorder endpoint because of a KMS disconnection
|
||||||
|
finalWrapper.setEndTime(
|
||||||
|
kmsDisconnectionTime != null ? kmsDisconnectionTime : System.currentTimeMillis());
|
||||||
|
generateIndividualMetadataFile(finalWrapper);
|
||||||
|
globalStopLatch.countDown();
|
||||||
|
log.warn("Forcing individual recording stop after {} for stream {} in recording {}",
|
||||||
|
kmsDisconnectionTime != null ? "KMS restart" : "node crashed", streamId,
|
||||||
|
recordingId);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
finalWrapper.getRecorder().addStoppedListener(new EventListener<StoppedEvent>() {
|
finalWrapper.getRecorder().addStoppedListener(new EventListener<StoppedEvent>() {
|
||||||
@Override
|
@Override
|
||||||
public void onEvent(StoppedEvent event) {
|
public void onEvent(StoppedEvent event) {
|
||||||
|
@ -301,14 +315,7 @@ public class SingleStreamRecordingService extends RecordingService {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
finalWrapper.getRecorder().stop();
|
finalWrapper.getRecorder().stop();
|
||||||
} else {
|
|
||||||
// Stopping recorder endpoint because of a KMS disconnection
|
|
||||||
finalWrapper.setEndTime(kmsDisconnectionTime);
|
|
||||||
generateIndividualMetadataFile(finalWrapper);
|
|
||||||
globalStopLatch.countDown();
|
|
||||||
log.warn(
|
|
||||||
"Forcing individual recording stop after KMS restart for stream {} in recording {}",
|
|
||||||
streamId, recordingId);
|
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
kParticipant.singleRecordingLock.unlock();
|
kParticipant.singleRecordingLock.unlock();
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
package io.openvidu.server.utils;
|
||||||
|
|
||||||
|
public class RemoteOperationUtils {
|
||||||
|
|
||||||
|
private final static String VALUE = "SKIP_REMOTE_OPERATION";
|
||||||
|
|
||||||
|
private static final ThreadLocal<String> threadLocal = ThreadLocal.withInitial(() -> "");
|
||||||
|
|
||||||
|
public static void setToSkipRemoteOperations() {
|
||||||
|
threadLocal.set(VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean mustSkipRemoteOperation() {
|
||||||
|
return VALUE.equals(threadLocal.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void revertToRunRemoteOperations() {
|
||||||
|
threadLocal.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue