Open Bug 814144 Opened 8 years ago Updated 5 years ago

Server Sent Event doesn't always retry

Categories

(Core :: DOM: Events, defect)

16 Branch
x86
All
defect
Not set
normal

Tracking

()

UNCONFIRMED

People

(Reporter: gary.tessman, Unassigned)

References

Details

(Whiteboard: [bugday-20131002])

Attachments

(1 file)

User Agent: Mozilla/5.0 (Windows NT 5.1; rv:17.0) Gecko/17.0 Firefox/17.0
Build ID: 20121119183901

Steps to reproduce:

Implemented Server Sent Events with retry set to 1000 (1 second) in spring mvc as a Controller service, and tried also Webservlet.  Send any message every 1 second by setting retry:
retry: 1000\n
data: hello world\n\n



Actual results:

Fails/disconnects in less than 10 minutes in Firefox on windows, mac version of 16.x.x.
Works forever in Chrome and Safari, but stops in a short period of time with Firefox.


Expected results:

Continual "retry" without dropping/disconnecting.  No error generated, just retry seems to be ignored after a few minutes.
Occurs in Mac OSX Lion, Windows 7 as well.
OS: Windows XP → Mac OS X
Please provide a testcase.
// Tomcat server.xml: 
//    <Connector port="8080" 
// 	       protocol="org.apache.coyote.http11.Http11NioProtocol" 
//                minProcessors="3" 
//                maxProcessors="8" 
//                maxThreads="20" 
//                connectionTimeout="150000" 
//                asyncTimeout="150000" />
------------------------------------------------------
Test Case 1 from Spring Controller: 
    @RequestMapping(value="/systemTime", method=RequestMethod.GET)
    public void sendMessage(Locale locale, HttpServletResponse response) {
        try {
            response.setContentType("text/event-stream");
            response.setCharacterEncoding("utf-8");
            response.setHeader("Cache-Control", "no-cache");
            response.setHeader("Connection", "keep-alive");

            DateFormat dateFormat = new SimpleDateFormat("MMMM dd, yyyy");
            DateFormat timeFormat = new SimpleDateFormat("h:mm:ss a");
            Date date = new Date();
            response.getWriter().
                append("retry: 1000\n").
                append("event: clock\n").
                append("data: {\"date\":\""+dateFormat.format(date)+"\",\"time\":\""+timeFormat.format(date)+"\"}\n\n");

            // Flush the response
            response.flushBuffer();
          }
          catch (IOException e) {
            e.printStackTrace();
          }
    }
------------------------------------------
Test Case 2 from WebServlet:
@WebServlet(value = "/clockevent", loadOnStartup = 1, asyncSupported = false)
public class SyncServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

@Override
  protected void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    response.setContentType("text/event-stream");
    response.setCharacterEncoding("utf-8");
    response.setHeader("Cache-Control", "no-cache");
    response.setHeader("Connection", "keep-alive");
    
    DateFormat dateFormat = new SimpleDateFormat("MMMM dd, yyyy");
    DateFormat timeFormat = new SimpleDateFormat("h:mm:ss a");
    Date date = new Date();
    response.getWriter().
        append("retry: 1000\n").
        append("event: clock\n").
        append("data: {\"date\":\""+dateFormat.format(date)+"\",\"time\":\""+timeFormat.format(date)+"\"}\n\n");
    
    // important, flush the response
    response.flushBuffer();

  }
}
------------------------------------------
Javascript:
	if (!!window.EventSource) {
		console.log("Server Sent Event available");
		var source = new EventSource("/servlet/clockevent2");
			
		source.addEventListener("clock", function(e) {
			var jsonobj = JSON.parse(e.data);
			$("#server-date").text(jsonobj.date);
			$("#server-time").text(jsonobj.time);
			console.log("Got clock event:"+e.data);
		}, false);

		source.addEventListener("open", function(e) {
			console.log("Server Sent Event connection opened...");
		}, false);

		source.addEventListener("error", function(e) {
			if (e.readyState == EventSource.CLOSED) {
				console.log("Server Sent Event connection closed.");
		    } else {
		    	if (e.readyState !== undefined){
		    		console.log(e.readyState);
		    	}
		    }
		}, false);
	} else {
		console.log("Server Sent Event not available");
		//TODO: Fallback to xhr
	}
---------------------------------------
Please let me know if you need more info.

Thanks, 
~Gary
Will need to change to the proper servlet to test:
var source = new EventSource("/servlet/clockevent");
OS: Mac OS X → All
Blocks: 338583
Component: Untriaged → DOM: Events
Product: Firefox → Core
Whiteboard: [bugday-20131002]
Attached file test
I've runned this test case for 40 minutes, 5 tabs opened at same time, in Linux without any failures.

I worked with J2EE some years ago. I remember that (depending on the configurations of the server) it was very common connections be dropped. So, it seems like this bug is duplicated of bug 831392.

Could you verify, please?
Flags: needinfo?(gary.tessman)
Thank you for giving this some attention.  You might want to try running it overnight based on my examples.  I ran it on OSX with Tomcat and Spring MVC 3.0 or 3.1 probably with Java 6.   Bug 831392 might be a duplicate of my bug since mine was created on 2012-11-21. 831392 was created afterwards on 2013-01-16.  The issues might be related however... in my bug the server wasn't stopped/restarted.   It was simply no reconnect after some time.  I'm not sure what might have changed since version 16 - but I can test it again if you'd like, or I can put together some Spring MVC demo and attach if your able to run it.  I also used Http11NioProtocol connector on tomcat.  It looks like your example uses PHP.  Might matter that it's Tomcat/Java and a flushBuffer() is actually a completed server side response. Since my examples above were using response.flushBuffer(); it commits the code to the client and returns status code like 200OK.  I assume this IS essentially a disconnect or completed request and should reconnect in this scenario.  Bug 831392 might be similar in that it's a server side disconnect except perhaps the status code returned maybe different or non-existent in the other bug.  However, based on the spec, and regardless of reason for disconnect - it should attempt to reconnect.  My examples did not reconnect after some sporadic duration of around 10-20 minutes using flushBuffer().  Let me know if you need me to followup in any way.  Thank you again!
Flags: needinfo?(gary.tessman)
Gary, could you make available your test case in web? Then, I could test in my computer here and look for the root cause.
You need to log in before you can comment on or make changes to this bug.