SuaveIO/suave

Socket error while running webpart

kMutagene opened this issue · 13 comments

I am using Suave on the server side of a SAFE stack application. I am sending a post request than contains an array of data, which is handled by the server. The server then applies a function to the data and returns the result. Depending on the size of the input array (an array of size 2 works charmless, an array of size 12 fails), The client reports the following error:

image

After making sure that the problem is not coming from fable.remoting, i turned on verbose logging in suave and get the following error displayed:

image

Is this problem related to some kind of timeout? I tried to look in the source code at ParsingAndControl.fs but had a hard time figuring out exactly why this error is thrown.

Any help would be greatly appreciated

Can we see your code? Or provide us with a POC?

I do see the logger is not outputting the exception details here which should be fixed and would help diagnosing this issue.

Hi @ademar, i am not sure which parts of the code are relevant here to avoid overflooding this thread with snippets. Maybe the first thing that could be of interest:

... which should be fixed and would help diagnosing this issue.

in which version is this fix located? i am currently running 2.5.0:
paket.dependencies:


group Server
    source https://api.nuget.org/v3/index.json
    framework: netcoreapp2.2
    storage: none

    nuget FSharp.Core
    nuget Suave 2.5.0.0
    nuget Fable.Remoting.Suave

It is not fixed yet, I just noticed.

Ah, i see.

I was able to reproduce this error without the usage of my actual function:

Here is the API in Shared.fs :

type TargetPModel =
|NoModel
|Plant
|NonPlant

type TargetPResult = {
    Header      : string
    Sequence    : string
    Scores      : float array
    PlotHtml    : string
}

/// A type that specifies the communication protocol between client and server
/// to learn more, read the docs at https://zaid-ajaj.github.io/Fable.Remoting/src/basics.html

type ITargetPApi = {
    SingleSequenceRequest : TargetPModel -> string -> Async<TargetPResult>
    FastaFileRequest : TargetPModel -> string -> Async<TargetPResult array>
    DownloadRequestSingle: TargetPResult*System.Guid -> Async<unit>
    DownloadRequestMultiple: TargetPResult array * System.Guid -> Async<unit>
}

Now if i just use a Thread.Sleep in the implementation on the Server side:

let targetPApi = {
    SingleSequenceRequest = 
        fun model single -> 
            async {
                    ...
            }
    FastaFileRequest = 
        fun model file -> 
            async {
                    Thread.Sleep(360000)
                    let result : TargetPResult [] = [||]
                    return result
                    }
    DownloadRequestSingle = 
        fun (res,id)-> 
            async { 
                    ...
                    }

    DownloadRequestMultiple = 
        fun (res,id) -> 
            async {
                   ...
                    }
}

I get the same error, i hope that helps.

Now if i just use a Thread.Sleep

You shouldn't use Thread.Sleep in async code but Async.Sleep instead.

I'll make it so it outputs the exception information in the error message and push a new version. Just give me some time because Mondays are very busy.

No worries, thanks for the help!

@kMutagene Can you also update your Suave references; I did not see previously that you are using 2.5.0 which is very old.

I've just pushed a new version 2.5.5 that should output the actual error/exception information if it is still happens.

Thank you very much, i will try it tomorrow!

Sorry for the late reply, i managed to see the error with the updated package.
It is a ConnectionAborted Error thrown by System.Net.Sockets. From the docs:

ConnectionAborted 10053 The connection was aborted by the .NET Framework or the underlying socket provider.

I did some more digging and the timeline of the error is the following:

  • get post request and start API function
  • After exactly two minutes in the chrome console:
    POST http://localhost:8080/api/ITargetPApi/FastaFileRequest net::ERR_EMPTY_RESPONSE
  • After the API function returns (at least the logging of Fable.Remoting tells me that the function is returning) the Suave log tells me:
    SocketError ConnectionAborted
    This error is not shown everytime, the only thing that is reproducible 100% of the time is the empty response.

So if i understand this right there is a max HTTP Connection timeout of two minutes? Can this be set in Suave (i only found listen timeout so far) or is this an issue that would be better to move to SAFE Stack?

Hi @kMutagene,

Difficult to know, these errors could be unrelated. ConnectionAborted is not necessarily a bad thing, it is usually shown when the client drops the connection.

To diagnose the issue I'll need a POC, the snippets do not show the full story and I am not familiar with the libraries you are using. If you could publish a repository with code reproducing the issue that will be great.

Hi @ademar ,

I will have to reproduce this error using another function then, because (to keep a rather long story short) i am accessing a docker container with the server side functions that need an academic licence. So i am afraid that i will need some time for this.

Sorry for letting this issue go stale for so long.

I found the problem, and it had nothing to do with suave. When using the SAFE-STACK, webpack is used to setup a dev server, which proxies requests to suave. Webpack has a default request timeout of 2 minutes. You can change it like this in the devServerProxy field of webpack.config:

    devServerProxy: {
        // redirect requests that start with /api/* to the server on port 8085
        '/api/*': {
            target: 'http://localhost:' + (process.env.SERVER_PROXY_PORT || "8085"),
            changeOrigin: true,
            proxyTimeout: 10 * 60 * 1000, // 10 minute timeout
            onProxyReq: (proxyReq, req, res) => req.setTimeout(10 * 60 * 1000) // 10 minute timeout
        }