Open D41138673 opened 2 years ago
The default timeout is 5 minutes. The dialogue is waiting up to 5 minutes to receive an input turn from the VoiceXML platform.
See https://nuecho.github.io/rivr/javadoc/com/nuecho/rivr/core/servlet/DialogueServlet.html
You can override the default globally by providing the com.nuecho.rivr.core.controllerTimeout
servlet init-arg with a different value.
In your case though, I would recommend overriding the timeout by providing a value in the DialogueUtils.doTurn method. See https://nuecho.github.io/rivr/javadoc/com/nuecho/rivr/core/dialogue/DialogueUtils.html#doTurn(O,%20com.nuecho.rivr.core.dialogue.DialogueContext,%20com.nuecho.rivr.core.util.Duration)
Currently we are facing problem other application through subdialog calling our application (developed using rivr framework) exising after 10 seconds but still rivr application flow is executing not returning control. So we are not sure why other application is getting the control back with "Exit" block without we send return. When we check the log rivr application is still executing the flow. I really approciate all your help on answering our questions
And tyo set the timeout we are not starting the subdialog other application is starting the subdialog and calling our application . When we check with them regarding timeout they set the timeout period as 5 mins. but currently dialog is terminating after 10 seconds
Is there any restriction calling restful web services (using RestTemplate) within rivr servlet in one of the step/turn?
10 seconds is the other timeout, i.e. the maximum time allowed for the dialogue to generate the next output turn. If the dialogue thread is making a backend query (like a REST call) and it takes more than 10 seconds, the servlet thread will time out. You can change the global timeout. See com.nuecho.rivr.core.dialogueTimeout
servlet init-arg in https://nuecho.github.io/rivr/javadoc/com/nuecho/rivr/core/servlet/DialogueServlet.html
When the servlet thread times out, the VoiceXML application will terminate with <exit>, because this is the default ErrorHandler. If you are implementing a VoiceXML subdialog, you might want to change the ErrorHandler to use your own custom implementation and use a <return> instead of <exit>, to ensure a failure in your dialogue will not terminate the calling dialogue (your calling IVR application in this case). Something like this:
package com.nuecho.rivr.cookbook.dialogue;
import com.nuecho.rivr.core.servlet.*;
import com.nuecho.rivr.voicexml.servlet.*;
import com.nuecho.rivr.voicexml.turn.last.*;
public class DialogueServlet extends VoiceXmlDialogueServlet {
@Override
protected void initializeVoiceXmlDialogueServlet() {
ErrorHandler<VoiceXmlLastTurn> customErrorHandler = new ErrorHandler<VoiceXmlLastTurn>() {
@Override
public Return handleError(Throwable error) {
String message = error.getMessage();
if (message == null) {
message = "no message";
}
return new Return("errorReturn", "error.subdialog.invoke", "dialogue error: " + message);
}
};
setErrorHandler(customErrorHandler);
}
}
Thank you details and this help us fix the issue . One more question if any of Rest API calls taking more time. To keep the customer engage planning to play some audio prompt until we get the response from API call. Is there anyway I can do this in asynchronously and use callback technique to stop playing audio prompt once API call completed. Now if we playing audio prompt 15 seconds it is playing entire 16 seconds even though API call completed with in 8 or 10 seconds
What you need is a fetch audio. A fetch audio is an audio file that will be played during the fetching of the next document until the document is completely fetched.
Here's two way to set a fetch audio.
1- Add the fetch audio to the submit element:
package com.nuecho.rivr.cookbook.dialogue;
import com.nuecho.rivr.core.dialogue.*;
import com.nuecho.rivr.voicexml.dialogue.*;
import com.nuecho.rivr.voicexml.turn.first.*;
import com.nuecho.rivr.voicexml.turn.input.*;
import com.nuecho.rivr.voicexml.turn.last.*;
import com.nuecho.rivr.voicexml.turn.output.*;
import com.nuecho.rivr.voicexml.turn.output.audio.*;
import com.nuecho.rivr.voicexml.turn.output.fetch.*;
public class Dialogue implements VoiceXmlDialogue {
@Override
public VoiceXmlLastTurn run(VoiceXmlFirstTurn firstTurn, VoiceXmlDialogueContext context)
throws Exception {
DocumentFetchConfiguration documentFetchConfiguration = new DocumentFetchConfiguration();
documentFetchConfiguration.setFetchAudio("/audio/fetch.wav");
context.getFetchConfiguration().setDocumentFetchConfiguration(documentFetchConfiguration);
Message waitMessage = OutputTurns.message("wait-message").addAudioItem(new SpeechSynthesis("Please wait while we obtain your information.")).build();
VoiceXmlInputTurn inputTurn = DialogueUtils.doTurn(waitMessage, context);
Thread.sleep(4000); // simlulate wait
Message resultMessage = OutputTurns.message("result")
.addAudioItem(new SpeechSynthesis("Your confirmation number is 8 9 1 3 2."))
.build();
inputTurn = DialogueUtils.doTurn(resultMessage, context);
//end of dialogue
return new Exit("exit");
}
}
This will add fetchaudio
to the submit element:
<submit fetchaudio="/audio/fetch.wav" method="post" namelist="inputTurn" next="/rivr-cookbook/dialogue/6e695c26-0860-4184-b6d1-152bce1f2c8f/0/wait-message"/>
2- Add fetch audio propoerties to the VoiceXML document:
package com.nuecho.rivr.cookbook.dialogue;
import com.nuecho.rivr.core.dialogue.*;
import com.nuecho.rivr.voicexml.dialogue.*;
import com.nuecho.rivr.voicexml.rendering.voicexml.*;
import com.nuecho.rivr.voicexml.turn.first.*;
import com.nuecho.rivr.voicexml.turn.input.*;
import com.nuecho.rivr.voicexml.turn.last.*;
import com.nuecho.rivr.voicexml.turn.output.*;
import com.nuecho.rivr.voicexml.turn.output.audio.*;
import com.nuecho.rivr.voicexml.turn.output.fetch.*;
public class Dialogue implements VoiceXmlDialogue {
@Override
public VoiceXmlLastTurn run(VoiceXmlFirstTurn firstTurn, VoiceXmlDialogueContext context)
throws Exception {
DefaultFetchConfiguration fetchConfiguration = context.getFetchConfiguration();
fetchConfiguration.setDefaultFetchAudio("/audio/fetch.wav");
//customize further the fetchaudio behavior:
context.getProperties().put(VoiceXmlDomUtil.FETCH_AUDIO_DELAY_PROPERTY, "1s"); //triggers after 1s
context.getProperties().put(VoiceXmlDomUtil.FETCH_AUDIO_MINIMUM_PROPERTY, "2s"); //plays at least 2s of fetch audio
Message waitMessage = OutputTurns.message("wait-message")
.addAudioItem(new SpeechSynthesis("Please wait while we obtain your information."))
.build();
VoiceXmlInputTurn inputTurn = DialogueUtils.doTurn(waitMessage, context);
Thread.sleep(4000); // simlulate wait
Message resultMessage = OutputTurns.message("result")
.addAudioItem(new SpeechSynthesis("Your confirmation number is 8 9 1 3 2."))
.build();
inputTurn = DialogueUtils.doTurn(resultMessage, context);
//end of dialogue
return new Exit("exit");
}
}
This will add the following properties to the document:
<?xml version="1.0" encoding="UTF-8"?>
<vxml application="/rivr-cookbook/dialogue/root/1939eccb-376a-4de1-b240-11d4152922e8" version="2.1" xmlns="http://www.w3.org/2001/vxml">
<script>application.rivr.localErrorHandling = false; application.rivr.inputTurn = {};</script>
<property name="fetchaudio" value="/audio/fetch.wav"/>
<property name="fetchaudiominimum" value="2s"/>
<property name="fetchaudiodelay" value="1s"/>
<form id="form">
<!-- ... -->
</form>
</vxml>
For both methods, the fetch audio will remain for the rest of the dialogue because it is set in the VoiceXmlDialogueContext
. So if it is no longer necessary following that point in the dialogue, the context should be reset to its previous state.
Thank you we will try these options and let you know result
10 seconds is the other timeout, i.e. the maximum time allowed for the dialogue to generate the next output turn. If the dialogue thread is making a backend query (like a REST call) and it takes more than 10 seconds, the servlet thread will time out. You can change the global timeout. See
com.nuecho.rivr.core.dialogueTimeout
servlet init-arg in https://nuecho.github.io/rivr/javadoc/com/nuecho/rivr/core/servlet/DialogueServlet.htmlWhen the servlet thread times out, the VoiceXML application will terminate with
, because this is the default ErrorHandler. If you are implementing a VoiceXML subdialog, you might want to change the ErrorHandler to use your own custom implementation and use a instead of , to ensure a failure in your dialogue will not terminate the calling dialogue (your calling IVR application in this case). Something like this: package com.nuecho.rivr.cookbook.dialogue; import com.nuecho.rivr.core.servlet.*; import com.nuecho.rivr.voicexml.servlet.*; import com.nuecho.rivr.voicexml.turn.last.*; public class DialogueServlet extends VoiceXmlDialogueServlet { @Override protected void initializeVoiceXmlDialogueServlet() { ErrorHandler<VoiceXmlLastTurn> customErrorHandler = new ErrorHandler<VoiceXmlLastTurn>() { @Override public Return handleError(Throwable error) { String message = error.getMessage(); if (message == null) { message = "no message"; } return new Return("errorReturn", "error.subdialog.invoke", "dialogue error: " + message); } }; setErrorHandler(customErrorHandler); } }
Is there any way we can get VoiceXmlDialogueContext in the handleError method?
No. It's not possible to obtain it from the handleError
method. Maybe in Rivr 2.0...
One of IVR application is transfering call using subdialog option to our application developed using Rivr framework. But they are getting "Dialog exiting" response from our application , even though rivr application logs shows control still processing the request. So before rivr application retrun the result back the cller application is terminating call saying they got the "Exit" response.
Is there any default timeout defined in thie rivr framework servlet "VoiceXmlDialogueServlet"