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

[jQuery] - streaming, onMessage is not fired when a lot requests made in short time #552

Closed
PavelR577 opened this issue Aug 8, 2012 · 12 comments

Comments

@PavelR577
Copy link

  1. open a channel (streaming)
  2. send a lot of messages (for example just hold the enter to keep it sending)
  3. onMessage is not fired on each message (I can see it in the firebug net tab that it returned to the client but it didn't get to the onMessage )

Tested with beta5,firefox/chrome tomcat 7.0.29

edit: looks like it happens only when I use the trackMessageLength:true

@PavelR577
Copy link
Author

after debugging couple of hours I found and fixed the issue.
Basiclly when you broadcast messages they sometimes can be broadcasted together (from what I understand this is by design), and in the _trackMessageSize func you assumed you'll have only 1 incoming message so when 2 messages arrived it was dropping both of them.
for example if we have a message 1|d and another one 1|c if they come one by one it works but when we get this 1|d1|c then it's an issue.
Updated: I've rewritten it at least 5 times (each time i find another issue), so I decided to drop the TrackMessageSizeFilter, so now for each message I send, I add a messageDelimiter at the end (my delimiter is @ cause it can't be sent by the user cause it will be encoded)

Each time I encounter the delimiter I know that I got a full message so I send it to the client and saving what's left for later use.
see code:

function _trackMessageSize(message, request, response) {

                if (request.trackMessageLength) {
                    var messages = [];
                    var messageEnd = message.indexOf(request.messageDelimiter);

                    //if no partial message from before then try to find full messages else -> append message to the partial one
                    if (response.partialMessage.length == 0) {
                        while (messageEnd != -1) {
                            var fullMessage = message.substring(0, messageEnd);
                            messages.push(fullMessage);
                            message = message.substring(messageEnd + request.messageDelimiter.length, message.length);
                            messageEnd = message.indexOf(request.messageDelimiter); //search for another full message

                        }
                    }

                    //check if partial message left
                    if (message.length != 0) {
                        response.partialMessage += message;
                    }


                    //not let's try to find full messages in the partial one
                    messageEnd = response.partialMessage.indexOf(request.messageDelimiter);
                    while (messageEnd != -1) {
                        fullMessage = response.partialMessage.substring(0, messageEnd); //get full message
                        messages.push(fullMessage);
                        response.partialMessage = response.partialMessage.substring(messageEnd + request.messageDelimiter.length, response.partialMessage.length); //remove the full message
                        messageEnd = response.partialMessage.indexOf(request.messageDelimiter); //search for another full message
                    }

                    if (messages.length != 0) {
                        response.responseBody = messages.join(request.messageDelimiter);
                        return false;
                    }
                    else
                        return true;

                } else {
                    response.responseBody = message;
                }
                return false;
            }

P.S - I'm still testing it and incase I'll find more issues I'll update the code here

@jfarcand
Copy link
Member

Salut, you start doing pull request instead :-) :-) How the testing went? Let me know if that works for you and I will update the code. If you can share a test case that would be good. Thanks!

@jfarcand
Copy link
Member

BTW, what was the issue with TrackMessageSizeFilter?

@PavelR577
Copy link
Author

Well, my fix currently working without any issues (so far)...
As to the TrackMessageSizeFilter - see previous post:
for example if we have a message 1|d and another one 1|c if they come one by one it works but when we get this 1|d1|c then it's an issue.

Just try sending 1|d1|c (simulate this message) and see that it breaks the logic

@jfarcand
Copy link
Member

Hum, I do get

Uncaught TypeError: Cannot read property 'length' of undefined 

on the first request with your patch :-)

@jfarcand
Copy link
Member

OK fixed that one, more testing now.

@jfarcand
Copy link
Member

OK the code above isn't working when TrackMessageFilter is used because the first block is adding the length instead of the message itself

@PrzemekPalak
Copy link

I think there is still problem with aggregated messages when using UUIDBroadcasterCache

@jfarcand
Copy link
Member

@PrzemekPalak Can you share a test case?

@PrzemekPalak
Copy link

Sure. I'm using modified JMSBroadcaster to work with Spring and Activemq, also using topic name instead of selector as broadcaster id. Test case simply publishes alot of messages to the topic. Her's the code:

    @ContextConfiguration(locations = {"classpath:/test-applicationContext.xml"})
    public class PublisherTest extends AbstractJUnit38SpringContextTests {

    @Autowired
    private ConnectionFactory connectionFactory;

    @Test
    public void testPublish() {
        Connection connection;
        Session publisherSession;
        MessageProducer publisher;
        Topic topic = new ActiveMQTopic("ATMOSPHERE.CHAT.MAIN");
        try {
            connection = connectionFactory.createConnection();
            publisherSession = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
            publisher = publisherSession.createProducer(topic);
            connection.start();
            for (int j = 0; j < 100; j++) {
                for (int i = 0; i < 100; i++) {
                    Response res = new Response("UnitTest", "hello " + i);
                    TextMessage textMessage = publisherSession.createTextMessage(res.toString());
                    //textMessage.setStringProperty("BroadcasterId", id);
                    publisher.send(textMessage);
                    System.out.println("Publishing msg " + i);
                    Thread.sleep(10);
                }
                Thread.sleep(300);
            }
            publisher.close();
            publisherSession.close();
            connection.close();
        } catch (JMSException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace(); 
        }
        assertNull(null);
    }

    }

@jfarcand
Copy link
Member

@PrzemekPalak Please send me reproducible test case, e.g a war I can drop and use as it is. Let's have the discussion on the mailing list

@PrzemekPalak
Copy link

Ok, I'll try to prepare something usable...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants