Git Product home page Git Product logo

Comments (10)

gdaws avatar gdaws commented on July 30, 2024

You might be mishandling client events. The client should be treated as disconnected after an error event.

The end event is emitted from the client after the connection closes and a disconnect receipt was received. This event is caused by a successful disconnect request. No reconnect is needed here.

The finish event is emitted from the client after initiating the disconnect request. The connection is still fully open at this point.

The error event is emitted from the client when the connection closes unexpectedly, i.e. the connection closes before receiving a disconnect receipt. This event is caused by one of many things and can originate from any side of the connection. This is when to consider a reconnect.

from stompit.

enVolt avatar enVolt commented on July 30, 2024

The client should be treated as disconnected after an error event.

By this you mean, error event in callback of stompit.connect method or something else.

This leads to another question, is there any difference between callback of client and stompClient, disconnect event can be listened on both. Is there any difference between error events of any of that?

stompClient = stompit.connect({
        host: config.server.host,
        port: config.server.port,
        connectHeaders: {
            'heart-beat': "10000,10000"
        }
    }, (error, client) => {
        if (error) {
            logger.debug("[AMQ-H] Error Occurred while Connecting", error);
            return;
        }
//        client.doSomething
    });

The error event is emitted from the client when the connection closes unexpectedly

Will this also trigger disconnect event?

What will happen if it misses a heartbeat (either from Server to client or vice-versa)?

from stompit.

gdaws avatar gdaws commented on July 30, 2024

By this you mean, error event in callback of stompit.connect method or something else.

I noticed that your error event handler is missing a isConnected = false; statement. On error event the client is disconnected.

An error event emitted from the client would be sent to all listeners. That includes external listeners added to the client using the EventEmitter interface (on method or addListener method) and temporary internal listeners that forward errors to callbacks.

This leads to another question, is there any difference between callback of client and stompClient, disconnect event can be listened on both. Is there any difference between error events of any of that?

No difference. stompClient and client point to the same object instance.

The connect callback is called on error event and receives an Error object. The same Error object is also passed to all the error event listeners on the client.

The error event is emitted from the client when the connection closes unexpectedly
Will this also trigger disconnect event?

No. The end event represents a successful disconnect from the server. To reach this state, the client sends a disconnect request, the server accepts delivery of any previously sent messages, the server sends a disconnect receipt, and then the connection closes.

What will happen if it misses a heartbeat (either from Server to client or vice-versa)?

A missed heartbeat from either side will cause an error event to be emitted from the client.

from stompit.

enVolt avatar enVolt commented on July 30, 2024

On error event the client is disconnected.

Is this true for all the error events? (I tried few basic cases, like sending invalid command (e.g client.sendFrame("TEST", {destination: "/bla/fsafsd"}).end(), which returned error unknown STOMP action: TEST, and client got disconnected; killing internet)
Just wanted to be sure.

Probably last question - Should I handle close end? As far as I was able to check, this is only triggered when socket is closed. Is it implicitely triggering end and finish event?

I've modified my application to trigger reconnect mechanism only on end event (or error, but not finish) event. Please suggest if you've any input on this.

from stompit.

gdaws avatar gdaws commented on July 30, 2024

On error event the client is disconnected.
Is this true for all the error events? (I tried few basic cases, like sending invalid command (e.g client.sendFrame("TEST", {destination: "/bla/fsafsd"}).end(), which returned error unknown STOMP action: TEST, and client got disconnected; killing internet)
Just wanted to be sure.

Yes it's true for all error events. The client ensures it's disconnected before emitting an error event. After an error event the client is dead and shouldn't emit events anymore.

Probably last question - Should I handle close end? As far as I was able to check, this is only triggered when socket is closed. Is it implicitely triggering end and finish event?

The client doesn't ever emit a close event.

The socket emits close event when the connection is closed in both directions. You may want to listen to this event to detect connection close in all cases, for instance when socket.destroy() is called. Calling the destroy method (with no arguments) doesn't cause an end event.

I've modified my application to trigger reconnect mechanism only on end event (or error, but not finish) event. Please suggest if you've any input on this.

The error event is the only event that should trigger a reconnect.

from stompit.

enVolt avatar enVolt commented on July 30, 2024

Thanks, @gdaws, this clears all the doubt about error events and when to kick reconnect. But still I can't get my head around random disconnection issue, I've set heartbeat at 10000,0, and my client is continuously dropping after 40-60 seconds (all the time, for last 24 hours) (getting connection ended without disconnect receipt).

This is what I was able to figure out -

lib/Socket.js #194

Socket.prototype._runHeartbeat = function(output, input) {
  output = output === 0 || this._heartbeat[0] === 0 ? 
    0 : Math.max(output, this._heartbeat[0]) - this._heartbeatOutputMargin;
  
  input = input === 0 || this._heartbeat[1] === 0 ? 
    0 : Math.max(input, this._heartbeat[1]) + this._heartbeatDelayMargin; 

this._heartbeat will be [10000, 0] in my case, on which server will respond with CONNECTED frame's header 0,10000. So output will be 0, and input will be 10000.

Frame should be like this (Verified, I used Wireshark to filter frames)

CONNECT
heart-beat:10000,0

CONNECTED:
heart-beat:0,10000

As per _runHeartBeat function's logic, both output === 0 || this._heartbeat[0] === 0 and input === 0 || this._heartbeat[1] === 0 will evaluate to true, and input and output will be 0.

What I'm able to deduct from here is, since there is no frame being sent by client in this case, after some time (in my case 40-60 seconds), ActiveMQ is explicitly killing my connection, thus I'm always getting connection ended without disconnect receipt.

Next thing I did was to modify this function as -

Socket.prototype._runHeartbeat = function(output, input) {
output = 10000; input = 0;  // Hardcoded just to test
  output = output === 0 || this._heartbeat[0] === 0 ? 
    0 : Math.max(output, this._heartbeat[0]) - this._heartbeatOutputMargin;
  
  input = input === 0 || this._heartbeat[1] === 0 ? 
    0 : Math.max(input, this._heartbeat[1]) + this._heartbeatDelayMargin; 

And after that, it is working fine (at least on my local), and from Wireshark, it is sending frames in a timely manner (almost 10 seconds).

Please correct me if I'm wrong somewhere, but if I'm correct this heartbeat piece is broken.

from stompit.

gdaws avatar gdaws commented on July 30, 2024

I believe you're correct about something being wrong with the _runHeartbeat function. Does swapping the order of the function parameters fix the issue?

from stompit.

enVolt avatar enVolt commented on July 30, 2024

That should work, from Stomp 1.1 Specs -

(cx, cy) = (10000, 0);

(sx, sy) = (0, 10000);

sx is output, and sy in input

For Client to Server

If either cx (_heartbeat[0]) or sy (input) is 0, then there will be no client to server heartbeat. (output's final value should be 0, to not heart client to server heartbeat), else Max (cx/_heartbeat[0], sy(input))

For Server to Client

If either sx (output) or cy (_heartbeat[1]) is 0, then there will be no server to client heartbeat. (input's final value should be 0, to not heart server to client heartbeat), else Max (sx/output, cy(_heartbeat[1]))

Value of output, should be calculated with _heartbeat[0] and input
Value of input, should be calculated with _heartbeat[1] and output

So yeah, switching them should work.

Raised a pull request, test cases are also working fine.

from stompit.

MinStenve avatar MinStenve commented on July 30, 2024

let option = { host:127.0.0.1, port: 61613, connectHeaders: { "host": "/", "login": "", "passcode": "", "heart-beat": "5000,0" //output input } };
it still emit error 'connection ended without disconnect receipt'

from stompit.

iravinandan avatar iravinandan commented on July 30, 2024

Even I am getting this issue that connection is ending without disconnect... Is any one got this fix?

from stompit.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.