watson-developer-cloud / java-sdk

:1st_place_medal: Java SDK to use the IBM Watson services.
http://watson-developer-cloud.github.io/java-sdk/
Apache License 2.0
590 stars 533 forks source link

[speech-to-text] websockets interface - internal threads never terminate (and more) #686

Closed assaftibm closed 7 years ago

assaftibm commented 7 years ago

JDK 1.8.0.131 java-sdk-3.8.0 Windows 7 64bit

I'm trying to build a desktop application in which a WAV file is selected, sent to IBM's speech to text service to obtain a transcript, the transcript is sent to some recipient, and after some time this process repeats.

I ran the code of RecognizeUsingWebSocketsExample as an example of using the WebSockets interface, but it seems like quite a lot of threads are created internally when the method recognizeUsingWebSocket() is called and never terminate. In fact, the program cannot finish its execution gracefully because the internal threads keep running forever (the main thread ends alright but the others don't). This is the threads view from Eclipse, right before the end of the main() method:

threads

You can see the several OkHTTP threads - Dispatcher, ConnectionPool, Watchdog, and again.

Moreover, subsequent calls to recognizeUsingWebSocket() in a loop with a short delay (12 seconds) between each call, results in more and more internal threads being created and never ending. I'm using a sample file that requires 6 seconds to transcribe, so each request should end within the delay of 12 seconds, and therefore the next call to recognizeUsingWebSocket() can reuse the threads already created for the previous call. However, this is not the case - the number of threads grows linearly with the number of calls to recognizeUsingWebSocket(), and 30 seconds after each call finished there is an error report saying: "Session timed out, no data received in the last 30 seconds.". This is the threads view after 5 calls to recognizeUsingWebSocket(), (with 12 sec delay between the calls, and with a transcription task that takes 6 seconds):

threads2

It looks like there are several problems here:

  1. The interface is missing a close() method that cleans up and ends the running threads, so the calling program can terminate gracefully.
  2. The resources allocated for one call of recognizeUsingWebSocket() are not reused for another (subsequent, not parallel) call of the same method.
  3. For each call to recognizeUsingWebSocket() there is an error report about timeout after 30 seconds. It looks as if it's impossible to avoid it - the client already sent a "stop" action, and the server responded with "listening" so they both know that the input has ended. It's unclear why there is an error report about no data for 30 seconds, and what else can be done to avoid the this error report. Even a subsequent call to recognizeUsingWebSocket() does not prevent the timeout from expiring.

To reproduce download the code and sample file from here.

germanattanasio commented 7 years ago

I'm making some changes to reuse the OkHttp ConnectionPool and OkioWatchdog. I also found a few interesting discussions around this topic.

assaftibm commented 7 years ago

Thanks!

germanattanasio commented 7 years ago

@assaftibm Once I merge #691 it will be in sonatype snapshots. Check the readme for instructions on how to use the snapshot repository

assaftibm commented 7 years ago

Can you link to the instructions how to use the snapshot repository? I found a link on the main page but didn't figure our how to use this repo. is there a way to tell gradle to download the new version from the snapshot repo instead of the standard maven repo? thanks again.

assaftibm commented 7 years ago

My question was answered by commit aa3ca857369c2f64a6d7c16dd183f2961bae7f85; latest info is on the README file.

DigitalZebra commented 7 years ago

Thanks for this @germanattanasio, unfortunately though this change removed the ability to configure a proxy server or similar for the Speech to Text service. We had been making use of the configureHttpClient method call in WatsonService to set up a proxy for the purposes of debugging, going through enterprise proxy, etc. Is there a new recommended way of doing this in light of the changes made in https://github.com/watson-developer-cloud/java-sdk/commit/3e1c6b6e36c42ef132aea2e5dfadf1722305d941 ?