Skip to content

Commit 50ad052

Browse files
committed
fix(model/tts): stoplatch safe problem when network loss
1 parent 2df268d commit 50ad052

1 file changed

Lines changed: 46 additions & 37 deletions

File tree

src/main/java/com/alibaba/dashscope/audio/ttsv2/SpeechSynthesizerV2.java

Lines changed: 46 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public final class SpeechSynthesizerV2 implements AudioWebsocketCallback {
3434
private SpeechSynthesisState state = SpeechSynthesisState.IDLE;
3535
private ResultCallback<SpeechSynthesisResult> callback;
3636

37-
private AtomicReference<CountDownLatch> stopLatch = new AtomicReference<>(null);
37+
private final AtomicReference<CountDownLatch> stopLatch = new AtomicReference<>(null);
3838

3939
private SpeechSynthesisParam parameters;
4040

@@ -48,7 +48,7 @@ public final class SpeechSynthesizerV2 implements AudioWebsocketCallback {
4848
private double recvAudioLength = 0;
4949
@Getter @Setter private long startedTimeout = 5000;
5050
@Getter @Setter private long firstAudioTimeout = -1;
51-
private AtomicReference<CountDownLatch> startLatch = new AtomicReference<>(null);
51+
private final AtomicReference<CountDownLatch> startLatch = new AtomicReference<>(null);
5252
private AudioWebsocketRequest websocketRequest;
5353
private String websocketUrl = Constants.baseWebsocketApiUrl;
5454
private JsonObject bailianHeader = new JsonObject();
@@ -102,8 +102,8 @@ public void updateParamAndCallback(
102102
this.canceled.set(false);
103103

104104
// reset inner params
105-
this.stopLatch = new AtomicReference<>(null);
106-
this.startLatch = new AtomicReference<>(null);
105+
this.stopLatch.set(null);
106+
this.startLatch.set(null);
107107
this.firstAudioTimeout = -1;
108108
this.isFirst = true;
109109
this.audioStream = new ByteArrayOutputStream();
@@ -168,6 +168,20 @@ public void close() {
168168
log.warn("Failed to close websocket connection: " + e.getMessage());
169169
}
170170
}
171+
releaseLatches();
172+
}
173+
174+
/** Release startLatch and stopLatch to unblock any waiting threads. */
175+
private void releaseLatches() {
176+
CountDownLatch startLatch = this.startLatch.get();
177+
if (startLatch != null && startLatch.getCount() > 0) {
178+
startLatch.countDown();
179+
}
180+
181+
CountDownLatch stopLatch = this.stopLatch.get();
182+
if (stopLatch != null && stopLatch.getCount() > 0) {
183+
stopLatch.countDown();
184+
}
171185
}
172186

173187
private synchronized void sendTaskMessage(String action, JsonObject input) {
@@ -308,16 +322,7 @@ public void onError(WebSocket webSocket, Throwable t) {
308322
// callback error first
309323
callback.onError(new ApiException(t));
310324
}
311-
312-
CountDownLatch startLatch = this.startLatch.get();
313-
if (startLatch != null && startLatch.getCount() > 0) {
314-
startLatch.countDown();
315-
}
316-
317-
CountDownLatch stopLatch = this.stopLatch.get();
318-
if (stopLatch != null && stopLatch.getCount() > 0) {
319-
stopLatch.countDown();
320-
}
325+
releaseLatches();
321326

322327
if (audioStream != null) {
323328
audioStream.reset();
@@ -327,21 +332,24 @@ public void onError(WebSocket webSocket, Throwable t) {
327332
@Override
328333
public void onClose(int code, String reason) {
329334
log.warn("WebSocket connection closed: " + reason + " (" + code + ")");
335+
releaseLatches();
330336
}
331337

332338
private void handleTaskStarted(JsonObject message) {
333339
log.info("Task started");
334340
state = SpeechSynthesisState.TTS_STARTED;
335341
firstPackageTimeStamp = -1;
336-
if (startLatch.get() != null) {
337-
startLatch.get().countDown();
342+
CountDownLatch startLatch = this.startLatch.get();
343+
if (startLatch != null) {
344+
startLatch.countDown();
338345
}
339346
}
340347

341348
private void handleTaskFinished(JsonObject message) {
342349
log.info("Task finished");
343-
if (stopLatch.get() != null) {
344-
stopLatch.get().countDown();
350+
CountDownLatch stopLatch = this.stopLatch.get();
351+
if (stopLatch != null) {
352+
stopLatch.countDown();
345353
}
346354
if (callback != null) {
347355
callback.onComplete();
@@ -370,8 +378,9 @@ private void handleTaskFailed(JsonObject message) {
370378
.build();
371379
callback.onError(new ApiException(status));
372380
}
373-
if (stopLatch.get() != null) {
374-
stopLatch.get().countDown();
381+
CountDownLatch stopLatch = this.stopLatch.get();
382+
if (stopLatch != null) {
383+
stopLatch.countDown();
375384
}
376385
}
377386

@@ -421,9 +430,10 @@ private void startStream(boolean enableSsml) throws NoApiKeyException, Interrupt
421430
}
422431

423432
checkConnectStatus(); // check websocket connection, if socket is closed.
424-
startLatch = new AtomicReference<>(new CountDownLatch(1));
433+
CountDownLatch startLatch = new CountDownLatch(1);
434+
this.startLatch.set(startLatch);
425435
startSynthesizer(enableSsml);
426-
boolean startResult = startLatch.get().await(startedTimeout, TimeUnit.MILLISECONDS);
436+
boolean startResult = startLatch.await(startedTimeout, TimeUnit.MILLISECONDS);
427437
if (!startResult) {
428438
throw new RuntimeException(
429439
"TimeoutError: waiting for task started more than " + startedTimeout + " ms.");
@@ -458,25 +468,24 @@ public void streamingComplete(long completeTimeoutMillis) {
458468
"State invalid: expect stream input tts state is started but " + state.getValue()));
459469
}
460470
}
461-
stopLatch = new AtomicReference<>(new CountDownLatch(1));
471+
CountDownLatch stopLatch = new CountDownLatch(1);
472+
this.stopLatch.set(stopLatch);
462473
stopSynthesizer();
463474

464-
if (stopLatch.get() != null) {
465-
try {
466-
if (completeTimeoutMillis > 0) {
467-
log.debug("start waiting for stopLatch");
468-
if (!stopLatch.get().await(completeTimeoutMillis, TimeUnit.MILLISECONDS)) {
469-
throw new RuntimeException("TimeoutError: waiting for streaming complete");
470-
}
471-
} else {
472-
log.debug("start waiting for stopLatch");
473-
stopLatch.get().await();
475+
try {
476+
if (completeTimeoutMillis > 0) {
477+
log.debug("start waiting for stopLatch");
478+
if (!stopLatch.await(completeTimeoutMillis, TimeUnit.MILLISECONDS)) {
479+
throw new RuntimeException("TimeoutError: waiting for streaming complete");
474480
}
475-
log.debug("stopLatch is done");
476-
} catch (InterruptedException ignored) {
477-
log.error("Interrupted while waiting for streaming complete");
478-
Thread.currentThread().interrupt();
481+
} else {
482+
log.debug("start waiting for stopLatch");
483+
stopLatch.await();
479484
}
485+
log.debug("stopLatch is done");
486+
} catch (InterruptedException ignored) {
487+
log.error("Interrupted while waiting for streaming complete");
488+
Thread.currentThread().interrupt();
480489
}
481490
}
482491

0 commit comments

Comments
 (0)