Blazor Server Side - Error: WebSocket closed with status code: 1006 () after 15 seconds - websocket

I have a Blazor Server Side app that throws a "Error: WebSocket closed with status code: 1006 () " on the clients side after 15 seconds while waiting for a sql query to complete.
The sql query populates a report so it sometimes takes up to 30 sec to generate.
I need to either increase the 15 sec timeout or keep the connection alive long enough for the query to complete.
Does anyone know how I can extend the timeout or keep the page alive long enough for the query to complete ?
Edit:
Adding :
endpoints.MapBlazorHub(opts => opts.WebSockets.CloseTimeout = new TimeSpan(1, 1, 1) );
to the start.cs seems to increase the time out to 30sec.
Unfortunately this doesn't seem to be enough off a timeout and changing the TimeSpan value any higher does not seem to increase the timeout further.
Thanks

I managed to "fix" this issue by doing a few things.
First I added
endpoints.MapBlazorHub(opts => opts.WebSockets.CloseTimeout = new TimeSpan(1, 1, 1));
to
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
in the
Startup.cs
This didn't completely work, it just increased the timeout from 15 sec to 30sec.
After playing around a bit, I updated the project from .net5 to .net 6 and updated all my nuget packages.
This seemed to help the most as the report now populates faster (under 30sec).
If I try to generate too large a report that takes over 30sec I now end up with a new error:
Error: Connection disconnected with error 'Error: Server timeout elapsed without receiving a message from the server.'.
If i keep refreshing the page the large reports does seem to eventually load.
For now the above fix helps me with my initial report issue.
If anyone has a real solution to this please let me know.
Edit(12/12/2022):
Finally seem to have a fix for this.
In _Host.cshtml
I added the following inside the "body" tag...
<body>
<script src="_framework/blazor.server.js" autostart="false"></script>
<script>
Blazor.start({
configureSignalR: function (builder) {
let c = builder.build();
c.serverTimeoutInMilliseconds = 3000000;
c.keepAliveIntervalInMilliseconds = 1500000;
builder.build = () => {
return c;
};
}
});
</script>
</body>
This, coupled with the "endpoints" update seems to have solved my issue correctly.

You can try:
WebSocket ws;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
ws = new WebSocket(new WebAssemblyHttpMessageHandler());
ws.SetReceiveTimeout(TimeSpan.FromSeconds(30));
await ws.ConnectAsync(new Uri("ws://localhost:5000/mywebsocket"));
}
}

Related

Parse Live Query Memory Leak

I'm using parse live query (in js and vue.js) to update/replace an array on each create. I noticed however that live query is causing a memory leak. As I'm running 3 live queries at at time, after day of running I get up to +2GB of memory and and error page with "out of memory".
Here an example of how I open one of my subscriptions.
Parse.initialize(this.parse.initialize)
Parse.serverURL = this.parse.serverURL
const snapshots = Parse.Object.extend("snapshots");
const query = new Parse.Query(snapshots)
const subscriptionSnapshots = await query.subscribe()
subscriptionSnapshots.on('open', () => {
console.log(' -> Snapshots subscription opened');
});
I don't know if it's related, but in my browser console I see the following alerts
[Violation] 'message' handler took <N>ms
parse.min.js:13 [Violation] 'message' handler took 164ms
Any ideas where the leak comes from and how I can stop it ?

Why am I getting Timeout error in the assertion step

I first tried this
let url = await pa.getPageURL("Employees");
console.log("URL "+url);
Then I tried this. Both are throwing time out error but printing the correct url.
it('should be able to open Employees page',async () => {
loginPg.login();
pa.getPageURL("Employees").then(function(url){
console.log("URL "+url);
expect(url).toContain("employees");
})
})
async getPageURL(pageName){
this.menu.click()
let url = element(by.xpath('//span[contains(.,"'+pageName+'")]')).click().then(function(){
return browser.getCurrentUrl();
})
return url;
}
I'm writing a test where it clicks on a page link from the menu and assert the url. It works fine and click the link and goes to the correct page.
I have also verified that the console.log is correctly printing the url in the above code. But it fails everytime with Timeout error.
Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
at ontimeout (timers.js:475:11)
at tryOnTimeout (timers.js:310:5)
What am I missing here? All my other tests work fine. Please help!
Try using a return keyword before your expect.
And also make sure to check DEFAULT_TIMEOUT_INTERVAL it will be 5 secs by default. Try changing it to 10 secs. So,That time is sufficient for logging in and then proceeding with actual expect.

Timer event in web api

I have created a timer event try to running in the background of my web api, I found it works fine when I debugger on local dev machine. However, The timer does not work when I added them to IIS on server. It stops after the first web request finishes( I tested it by writing some text into log files, it seems stopped after a few triggers, once the web request completed)
Here is some example code.
void refreshTimeStart()
{
refreshTimer = new System.Timers.Timer(Convert.ToInt32(ConfigurationManager.AppSettings["TIMER_INTERVAL"]));
refreshTimer.Elapsed += new ElapsedEventHandler(connectionResetEvent);
refreshTimer.AutoReset = true;
refreshTimer.Enabled = true;
}
void connectionResetEvent(object source, ElapsedEventArgs e)
{
testIndex = testIndex + 1;
WriteToFile(testIndex);
}
static void WriteToFile(int i)
{
string text = "This start trigged. ";
System.IO.File.WriteAllText(#"C:\Projects\abc" + i.ToString() + ".txt", text);
}
Any idea of how to achieve this? Thanks a lot.
The question was asked a long time ago but here's an answer anyway.
First of all, using a timer in a Web API is probably not the best idea. A windows service would be more appropriate. That being said, your problem must come from two issues:
a Web API awaits a request and only initializes after the first request. So you'll have to initiate a request for your timer to start.
the default settings of application pools in IIS have a timeout. So even if you initialize the Web API, the application pool will terminate after the timeout period has elapsed. You could disable the timeout.

Async sends in .NET ActiveMQ

I'm looking to increase the performance of a high-throughput producer that I'm writing against ActiveMQ, and according to this useAsyncSend will:
Forces the use of Async Sends which adds a massive performance boost;
but means that the send() method will return immediately whether the
message has been sent or not which could lead to message loss.
However I can't see it making any difference to my simple test case.
Using this very basic application:
const string QueueName = "....";
const string Uri = "....";
static readonly Stopwatch TotalRuntime = new Stopwatch();
static void Main(string[] args)
{
TotalRuntime.Start();
SendMessage();
Console.ReadLine();
}
static void SendMessage()
{
var session = CreateSession();
var destination = session.GetQueue(QueueName);
var producer = session.CreateProducer(destination);
Console.WriteLine("Ready to send 700 messages");
Console.ReadLine();
var body = new byte[600*1024];
Parallel.For(0, 700, i => SendMessage(producer, i, body, session));
}
static void SendMessage(IMessageProducer producer, int i, byte[] body, ISession session)
{
var message = session.CreateBytesMessage(body);
var sw = new Stopwatch();
sw.Start();
producer.Send(message);
sw.Stop();
Console.WriteLine("Running for {0}ms: Sent message {1} blocked for {2}ms",
TotalRuntime.ElapsedMilliseconds,
i,
sw.ElapsedMilliseconds);
}
static ISession CreateSession()
{
var connectionFactory = new ConnectionFactory(Uri)
{
AsyncSend = true,
CopyMessageOnSend = false
};
var connection = connectionFactory.CreateConnection();
connection.Start();
var session = connection.CreateSession(AcknowledgementMode.AutoAcknowledge);
return session;
}
I get the following output:
Ready to send 700 messages
Running for 2430ms: Sent message 696 blocked for 12ms
Running for 4275ms: Sent message 348 blocked for 1858ms
Running for 5106ms: Sent message 609 blocked for 2689ms
Running for 5924ms: Sent message 1 blocked for 2535ms
Running for 6749ms: Sent message 88 blocked for 1860ms
Running for 7537ms: Sent message 610 blocked for 2429ms
Running for 8340ms: Sent message 175 blocked for 2451ms
Running for 9163ms: Sent message 89 blocked for 2413ms
.....
Which shows that each message takes about 800ms to send and the call to session.Send() blocks for about two and a half seconds. Even though the documentation says that
"send() method will return immediately"
Also these number are basically the same if I either change the parallel for to a normal for loop or change the AsyncSend = true to AlwaysSyncSend = true so I don't believe that the async switch is working at all...
Can anyone see what I'm missing here to make the send asynchronous?
After further testing:
According to ANTS performance profiler that vast majority of the runtime is being spent waiting for synchronization. It appears that the issue is that the various transport classes block internally through monitors. In particular I seem to get hung up on the MutexTransport's OneWay method which only allows one thread to access it at a time.
It looks as though the call to Send will block until the previous message has completed, this explains why my output shows that the first message blocked for 12ms, while the next took 1858ms. I can have multiple transports by implementing a connection-per-message pattern which improves matters and makes the message sends work in parallel, but greatly increases the time to send a single message, and uses up so many resources that it doesn't seem like the right solution.
I've retested all of this with 1.5.6 and haven't seen any difference.
As always the best thing to do is update to the latest version (1.5.6 at the time of this writing). A send can block if the broker has producer flow control enabled and you've reached a queue size limit although with async send this shouldn't happen unless you are sending with a producerWindowSize set. One good way to get help is to create a test case and submit it via a Jira issue to the NMS.ActiveMQ site so that we can look into it using your test code. There have been many fixes since 1.5.1 so I'd recommend giving that new version a try as it could already be a non-issue.

HttpWebRequest.BeginGetResponse completes too late

I use in my code calls to HttpWebRequest.BeginGetResponse() method to get data from my server. The server produces content that may range from few KB to few GB.
My problem is that HttpWebRequest.BeginGetResponse completes too late. It should complete immediately after the connection to the server is established and the HTTP header is received.
Here is sample code using GET method:
public bool StartDownload()
{
try
{
HttpWebRequest myHttpWebRequest = (HttpWebRequest)WebRequest.Create(m_getUrl);
myHttpWebRequest.Method = "GET";
// Start the asynchronous request.
m_requestState = new RequestState();
m_requestState.request = myHttpWebRequest;
myHttpWebRequest.BeginGetResponse(new AsyncCallback(ResponseCompleted), m_requestState);
}
catch (Exception)
{
m_requestState = null;
}
return m_requestState != null;
}
private void ResponseCompleted(IAsyncResult result)
{
RequestState myRequestState = (RequestState)result.AsyncState;
HttpWebRequest myHttpWebRequest = myRequestState.request;
m_logger.LogMessage("ResponseCompleted notification received!");
HttpWebResponse response = null;
try
{
response = (HttpWebResponse)myHttpWebRequest.EndGetResponse(result);
}
catch (Exception)
{
}
.......
}
I run the code using "http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.39.1.tar.bz2" for example and the result looks like:
hh:mm:ss.ms
12:51:30.9440000 - Download started!
12:53:04.8520000 - ResponseCompleted notification received!
12:53:04.8560000 - Header received!
12:53:04.8570000 - DataReceived: 524288 bytes
.........................................
12:53:04.8940000 - DataReceived: 78818 bytes
12:53:04.8940000 - Request data received!
12:53:04.8940000 - Received bytes: 76100578
The problem can be easily detected in the log. It is not possible to spend more that one minute to connect and 38 ms to download about 72.5 MB.
It seems that the data is downloaded somewhere on the phone and the RequestComplete notification is sent to the application only when the full content is available locally. This is not OK for me because I need to show progress for the operation.
I get the same result on the device and emulator for WP7 (also on WP7.1).
I run same code on Windows desktop and it run correctly: the request completes within one second and the rest of the download takes about 1-2 minutes.
Is there any solution on WP7 or WP 7.1?
The newly introduced WP 7.1 API "Background File Transfers" does not help because I need full control over the HTTP headers and content. Not all HTTP requests that I make to the server produce files as output.
Thank you!
Mihai
You need to disable response buffering if you want to stream the data down. You can do this by setting AllowReadStreamBuffering to false.
HttpWebRequest myHttpWebRequest = WebRequest.CreateHttp(m_getUrl);
myHttpWebRequest.Method = "GET";
myHttpWebRequest.AllowReadStreamBuffering = false;

Resources