Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement WebSocket message retrieval #142

Closed
arieschwartzman opened this issue Nov 16, 2016 · 32 comments
Closed

Implement WebSocket message retrieval #142

arieschwartzman opened this issue Nov 16, 2016 · 32 comments
Assignees

Comments

@arieschwartzman
Copy link

The version of the WebChat still using polling to get messages. How do I activate the WebSocket new feature?

@billba billba self-assigned this Nov 16, 2016
@billba
Copy link
Member

billba commented Nov 16, 2016

Direct Line 3.0 allows both GET and WebSocket to retrieve messages. We do plan to implement WebSocket support in WebChat in the future, but it's not available yet.

@billba billba changed the title Still seeing polling every second. Implement WebSocket message retrieval Nov 16, 2016
@billba billba added this to the After Belfast milestone Nov 16, 2016
@arieschwartzman
Copy link
Author

Great, thanks

@billba
Copy link
Member

billba commented Nov 16, 2016

Note that even once WebSocket is implemented, WebChat will still fallback to GET if the browser does not support WebSocket.

@billba
Copy link
Member

billba commented Dec 12, 2016

This is now working on a preview basis. You can pass webSocket: true when creating DirectLine. Or if you're using the provided samples/index.html, you can pass webSocket=true in the URL.

I will keep this issue open until we make WebSocket the default transport for receiving messages.

@stephaneey
Copy link

stephaneey commented Jan 12, 2017

Hi,

For me websockets don't work. I keep getting the following error (visible only when debugging):

"Failed to construct 'WebSocket':
The URL 'v3/directline/conversations/9eRq1bOKuvU14n92KhViVH/stream?
watermark=-&t=GJdVApD6wRY.dA...DkAMgBLAGgAVgBpAFYAS
AA.qqdbi9ls0gE.MdTQRQVZwVk.38QPHxDs6DKLXPegWTTJq1CO9H615ITl2qvuxE_M7cs' is invalid."

I'm using the provided /samples/index.html page. You mentioend public/index.html but the only think I found there is a page showing a turtle...So, passing the webSocket=true parameter just fails. Any idea why?

Also, using the out of the box endpoint https://webchat.botframework.com/embed, webSocket has no effect although the enable preview checkbox is ticked in the webchat channel config. Are websockets usable with the online control or only via a custom built one?

Thanks

@billba
Copy link
Member

billba commented Jan 12, 2017

WebSocket is still in beta, and is not currently available in the preview version of the hosted WebChat channel, so yes you currently need to build your own control and enable WebSockets.

I updated the above comment to reflect the change from public -> samples, thanks.

I use WebChat with WebSockets most of the time, and they work fine for me so we'll have to dig into your details. What version of which browser are you using, how are you embedding the control? Are you just running samples/index.html directly, and if so can you provide the URL you're using (redacting your direct line secret of course).

@stephaneey
Copy link

stephaneey commented Jan 12, 2017

Hi Bill,

thanks for your swift reply. I tried again and here is the full info:
URL I'm using:
http://169.254.46.96:8000/samples/index.html?s=GJdVApD__________-iRY_phHzffffhiuNtyTRSmjTZ2dA&webSocket=true

(I've obfuscated part of the secret here)

The code is going to the catch block of the following method:
private __tryOrSetError(parent: Subscriber, fn: Function, value?: any): boolean {
try {
fn.call(this._context, value);
} catch (err) {
parent.syncErrorValue = err;
parent.syncErrorThrown = true;
return true;
}
return false;
}
that is part of the Subscriber.ts script.

Returned error:

error code 12
message : "Failed to construct 'WebSocket': The URL 'v3/directline/conversations/7N8Dwv9jY7CErSVMEKXGiI/stream?watermark=-&t=GJdVApD6wRY.dAA.NwBOADgARAB3AHYAOQBqAFkANwBDAEUAcgBTAFYATQBFAEsAWABHAGkASQA.EWA0NPxs0gE.tnN4IL3pOJ8.zgg3uY5aWn5TW_kW4wkpwuW1BoARVQmjO7iuZ3yJ2f8' is invalid."
name : "SyntaxError"
stack : "Error: Failed to construct 'WebSocket': The URL 'v3/directline/conversations/7N8Dwv9jY7CErSVMEKXGiI/stream?watermark=-&t=GJdVApD6wRY.dAA.NwBOADgARAB3AHYAOQBqAFkANwBDAEUAcgBTAFYATQBFAEsAWABHAGkASQA.EWA0NPxs0gE.tnN4IL3pOJ8.zgg3uY5aWn5TW_kW4wkpwuW1BoARVQmjO7iuZ3yJ2f8' is invalid.
at Observable._subscribe (http://169.254.46.96:8000/webpacked/botchat.js:51264:23)
at Observable.subscribe (http://169.254.46.96:8000/webpacked/botchat.js:22235:28)
at RetryWhenOperator.call (http://169.254.46.96:8000/webpacked/botchat.js:35270:24)
at Observable.subscribe (http://169.254.46.96:8000/webpacked/botchat.js:22232:23)
at Object.subscribeToResult (http://169.254.46.96:8000/webpacked/botchat.js:24034:28)
at MergeMapSubscriber._innerSub (http://169.254.46.96:8000/webpacked/botchat.js:29958:39)
at MergeMapSubscriber._tryNext (http://169.254.46.96:8000/webpacked/botchat.js:29955:15)
at MergeMapSubscriber._next (http://169.254.46.96:8000/webpacked/botchat.js:29938:19)
at MergeMapSubscriber.Subscriber.next (http://169.254.46.96:8000/webpacked/botchat.js:22457:19)
at MergeMapSubscriber.notifyNext (http://169.254.46.96:8000/webpacked/botchat.js:29971:31)"

I tried with Chrome Version 55.0.2883.87 m but also with Firefox and Edge on two different machines and they all end up with the above error.

You now have the full info. Hope this helps and thanks again!

Edit : I realized that I forgot to mention how I call the page, I'm just running the URL directly in the browser, no embed.

Best Regards

@billba
Copy link
Member

billba commented Jan 12, 2017

That URL is very odd - it should look more like wss://directline.botframework.com/v3/directline/conversations/{conversationId}/stream?watermark=-&t={token}

Will you add a console.log("streamUrl", this.streamUrl); right after here and let me know what it says?

@stephaneey
Copy link

Here is what I get from Fiddler :
{
"conversationId": "HR2oZYGenM6EQKzX5Q4c7h",
"token": "GJdVApD6wRY.dAA.SABSADIAbwBaAFkARwBlAG4ATQA2AEUAUQBLAHoAWAA1AFEANABjADcAaAA.jge4ygZt0gE.vfFj4ifohWk.djNV-z2_t3kq8uQ0MctFPIB_Ng9BaJBCDKJ0hkUgnNA",
"expires_in": 1800,
"streamUrl": "v3/directline/conversations/HR2oZYGenM6EQKzX5Q4c7h/stream?watermark=-&t=GJdVApD6wRY.dAA.SABSADIAbwBaAFkARwBlAG4ATQA2AEUAUQBLAHoAWAA1AFEANABjADcAaAA.jhmZvQJt0gE.gRqIJyP5ztI.pqd8snmDug9myJzu0xqjxO0u5EeuK_UP2yLQ1cRlI-Q"
}
and here is what is logged in the console as you suggested:

v3/directline/conversations/HR2oZYGenM6EQKzX5Q4c7h/stream?watermark=-&t=GJdVApD6wRY.dAA.SABSADIAbwBaAFkARwBlAG4ATQA2AEUAUQBLAHoAWAA1AFEANABjADcAaAA.jhmZvQJt0gE.gRqIJyP5ztI.pqd8snmDug9myJzu0xqjxO0u5EeuK_UP2yLQ1cRlI-Q

The URL matches, I guess that you should concatenate wss:...+the url returned by directline?

Thanks

@billba
Copy link
Member

billba commented Jan 12, 2017

No, you should be getting the full URL. I'll pursue this and get back to you, thanks.

@stephaneey
Copy link

Of course, just doing this:

if(this.streamUrl.indexOf('wss')==-1)
{
this.streamUrl = 'wss://directline.botframework.com/'+this.streamUrl;
}
in directLine.ts does the trick but it's not very elegant. However, I have rebuilt and now websockets work fine.

@billba
Copy link
Member

billba commented Jan 12, 2017

@stephaneey you shouldn't need to do that but I'm glad you're unblocked for now.

Anyone else seeing this problem?

P.S. if (this.streamUrl.startsWith('wss')) ... - the magic of ES6!

@stephaneey
Copy link

stephaneey commented Jan 13, 2017

Bill, another issue once you switch to webSocket is whenever I send a message, there is alternate HTTP post query (regular AJAX) that is systematically cancelled (see screenshot), causing the chat window to display "couldn't send...retry" for a while. With Edge and Firefox, the requests remain in "pending" as they use the "keep-alive" mechanism but every message creates a new connection. Display behavior is the same, it goes always in the "retry" mode.

It is a normal behavior to still send HTTP Post request intead of reusing the webSocket channel?

Chrome
errobot

Edge
boterror

Thanks

@billba
Copy link
Member

billba commented Jan 13, 2017

we only use WebSockets to receive messages, so this is yet a different strange behavior you are seeing that i've never seen or heard of before. Is your computer cursed?

@stephaneey
Copy link

stephaneey commented Jan 13, 2017

ah ah :), same behavior again on two different machines and with 3 different browsers and with different wireless networks so I guess, this can't be my machine.
[edit:same on iPad], so it can't be a machine problem.

@stephaneey
Copy link

Bill, are you using the exact same version as the one that's currently available in this repo?

@billba
Copy link
Member

billba commented Jan 13, 2017

I sure am. So the one thing in common is that all these machines/browsers/networks are aiming at the same bot?

@billba
Copy link
Member

billba commented Jan 13, 2017

Will you set var botchatDebug=true in the console and see if you see any messages about web sockets being closed?

@stephaneey
Copy link

Here is the output when I send a message:

history action Object {type: "Send_Message", activity: Object}
botchat.js:21793 history action Object {type: "Send_Message_Try", clientActivityId: "1484323244757.3722033363586965.0"}
botchat.js:21793 postActivity Object {type: "message", text: "blabla", from: Object, locale: "fr", timestamp: "2017-01-13T16:00:59.202Z"…}
botchat.js:21793 history action Object {type: "Show_Typing", activity: Object}
botchat.js:21793 history action Object {type: null}
botchat.js:21793 history action Object {type: "Receive_Message", activity: Object}
botchat.js:21793 history action Object {type: "Clear_Typing", id: "BbmRWIVGy2xKWuy4cd3EBX|9n6SgL8Iwm"}
botchat.js:21793 history action Object {type: null}
botchat.js:21793 history action Object {type: "Send_Message_Succeed", clientActivityId: "1484323244757.3722033363586965.0", id: "retry"}
botchat.js:21793 history action Object {type: null}
botchat.js:21793 history action Object {type: "Receive_Sent_Message", activity: Object}activity: Objecttype: "Receive_Sent_Message"proto: Object

and indeed, they all aim at the same bot, I will try with another one just to see

@stephaneey
Copy link

stephaneey commented Jan 13, 2017

Ok I think I found the culprit : the timeout. I just amended my bot in order to simply answer "hello" whatever message is received and now, I don't have this problem anymore. If the bot takes more than 5 seconds (which is the case because it performs several sharepoint queries in a row after an interaction with LUIS). So, that's the reason. I noticed that the default timeout is 5000 milliseconds but I didn't really find where you defined that in the source code as things seems to be commented out. Note this seems specific to webSockets as I never faced this issue with the polling get mode..

@stephaneey
Copy link

stephaneey commented Jan 13, 2017

I found a crappy way of increasing it but this made the trick:

for (var prop in urlOrRequest) {
if (urlOrRequest.hasOwnProperty(prop)) {
if (prop != 'timeout') {
request[prop] = urlOrRequest[prop];
}else
{
request[prop] = 10000;
}
}
}
and no more issue...if you could just indicate where the default timeout of 5000 is specified, that'd be great as I didn't manage to find it (made a search on 5000 in the entire folder...but no luck)

To be honest, 5000 is way too short if you work with LUIS dialogs. Simply resolving to the None intent and replying "I don't understand" is usually taking already about 5/6 seconds. This is increased by the 'typing' reply but even when removing it, it's really hard to get the right LUIS intent triggered below 5 secs.

thanks

@billba
Copy link
Member

billba commented Jan 13, 2017

That's great feedback, thanks. 5 secs was totally arbitrary. What do you personally think would be the right number? 10? 15? 20? The reason we have a limit at all is so that we can give up on a particular server instance that might be sick but not immediately failing, and hope we get a better one on the next try.

Here is where this is set in the code.

@stephaneey
Copy link

I think that at least 10 secs is necessary :)

@billba
Copy link
Member

billba commented Jan 13, 2017

I was low on coffee when I responded before.

The short timeout isn't a problem. Bots aren't synchronous. The DirectLine call to post an activity isn't waiting for your bot to respond, it's just posting your message into a queue and immediately returning. 5 seconds is a very reasonable amount of time for this to happen, but I might bump it up a bit.

Whether your bot takes a second to respond or ten minutes shouldn't be relevant at all. I just made a bot that takes 10 seconds to respond, and accessed it with WebSocket. Posting happened right away. The response took 10 seconds, as planned.

There is something weird going on with your bot, but I have no idea what it is.

@stephaneey
Copy link

stephaneey commented Jan 13, 2017

Well, if I simply do this into my bot:

var cli = new ConnectorClient(new Uri(activity.ServiceUrl));
var rep = activity.CreateReply("test");
Thread.Sleep(16000); // now I've built the chat control with 15 secs
await cli.Conversations.ReplyToActivityAsync(rep);

after the switch block, there is also
var response = Request.CreateResponse(HttpStatusCode.OK);
return response;

I reproduce the issue and the bot couldn't be simpler, so what am I missing here? So, whether they are synchronous or not, getting over the timeout results in that on all machines.

PS, here is the screenshot of the network call from Chrome, as you can see (highlighted in red) it stops right after the timeout:

botitmeout

Thanks
Best Regards

@stephaneey
Copy link

Bill, to add some more info, as you probably noticed yourself, this timeout issue isn't limited to webSocket, I get the exact same thing with polling get but there are many requests going on, that it is not as noticable as it is with websockets

pollingget

You see here, it fails after 5.01 seconds, the default timeout since I'm using the online webchat control against the same bot that I described above (sleeping 16 seconds). So, the HTTP post query waits until the bot responds and timeouts, even with the online webchat which we cannot configure.

Thanks
Best Regards

@billba
Copy link
Member

billba commented Jan 17, 2017

@stephaneey Okay I have an answer for your WebSocket problem. You registered your bot for the WebChat channel and are using the secret it gave you. But actually you need to register it for DirectLine and use that secret. This is causing the bug. In the future it won't even work at all to use a WebChat secret at DirectLine endpoints.

Will you please open up a separate issue for the other problem you're experiencing?

@stephaneey
Copy link

stephaneey commented Jan 17, 2017

Hi Bill,

I confirm that I was indeed using the secret given by the webchat control. How is it going to work when you'll enable websockets with the online control because this is quite confusing.

Ok so this fixes the streamurl problem right but it doesn't explain the timeout thing, right?

Thanks

@billba
Copy link
Member

billba commented Jan 17, 2017

Right, that's why I asked you to file a separate issue. I agree that the naming is confusing. This is not a WebSockets issue, that was just a random bug. We will eventually enable WebSockets by default for the WebChat channel.

@billba
Copy link
Member

billba commented Jan 17, 2017

@stephaneey Ah I think I misunderstood your question. The reason this bug exists is that you were passing WebChat secrets to a DirectLine endpoint. Folks using WebChat secrets with the WebChat endpoint will have no problems, and soon the respective endpoints will only accept their own secrets.

@stephaneey
Copy link

@billba that's indeed what I meant. I created a separate issue #288 for the network problem.

Best Regards

@billba
Copy link
Member

billba commented Feb 2, 2017

Now on by default (but currently off in the official WebChat channel)

@billba billba closed this as completed Feb 2, 2017
@eanders-ms eanders-ms modified the milestone: After Belfast Aug 17, 2017
compulim pushed a commit to compulim/BotFramework-WebChat that referenced this issue Jul 14, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants