mirror of
				https://github.com/zulip/zulip.git
				synced 2025-10-31 03:53:50 +00:00 
			
		
		
		
	Zulip has had a small use of WebSockets (specifically, for the code path of sending messages, via the webapp only) since ~2013. We originally added this use of WebSockets in the hope that the latency benefits of doing so would allow us to avoid implementing a markdown local echo; they were not. Further, HTTP/2 may have eliminated the latency difference we hoped to exploit by using WebSockets in any case. While we’d originally imagined using WebSockets for other endpoints, there was never a good justification for moving more components to the WebSockets system. This WebSockets code path had a lot of downsides/complexity, including: * The messy hack involving constructing an emulated request object to hook into doing Django requests. * The `message_senders` queue processor system, which increases RAM needs and must be provisioned independently from the rest of the server). * A duplicate check_send_receive_time Nagios test specific to WebSockets. * The requirement for users to have their firewalls/NATs allow WebSocket connections, and a setting to disable them for networks where WebSockets don’t work. * Dependencies on the SockJS family of libraries, which has at times been poorly maintained, and periodically throws random JavaScript exceptions in our production environments without a deep enough traceback to effectively investigate. * A total of about 1600 lines of our code related to the feature. * Increased load on the Tornado system, especially around a Zulip server restart, and especially for large installations like zulipchat.com, resulting in extra delay before messages can be sent again. As detailed in https://github.com/zulip/zulip/pull/12862#issuecomment-536152397, it appears that removing WebSockets moderately increases the time it takes for the `send_message` API query to return from the server, but does not significantly change the time between when a message is sent and when it is received by clients. We don’t understand the reason for that change (suggesting the possibility of a measurement error), and even if it is a real change, we consider that potential small latency regression to be acceptable. If we later want WebSockets, we’ll likely want to just use Django Channels. Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
		
			
				
	
	
		
			55 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			55 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| // Miscellaneous early setup.
 | ||
| 
 | ||
| $(function () {
 | ||
|     if (util.is_mobile()) {
 | ||
|         // Disable the tutorial; it's ugly on mobile.
 | ||
|         page_params.needs_tutorial = false;
 | ||
|     }
 | ||
| 
 | ||
|     page_params.page_load_time = new Date().getTime();
 | ||
| 
 | ||
|     // Display loading indicator.  This disappears after the first
 | ||
|     // get_events completes.
 | ||
|     if (page_params.have_initial_messages && !page_params.needs_tutorial) {
 | ||
|         loading.make_indicator($('#page_loading_indicator'), {text: 'Loading...', abs_positioned: true});
 | ||
|     } else if (!page_params.needs_tutorial) {
 | ||
|         $('#first_run_message').show();
 | ||
|     }
 | ||
| 
 | ||
|     // This is an issue fix where in jQuery v3 the result of outerHeight on a node
 | ||
|     // that doesn’t exist is now “undefined” rather than “null”, which means it
 | ||
|     // will no longer cast to a Number but rather NaN. For this, we create the
 | ||
|     // `safeOuterHeight` and `safeOuterWidth` functions to safely return a result
 | ||
|     // (or 0).
 | ||
|     $.fn.safeOuterHeight = function () {
 | ||
|         return $(this).outerHeight.apply(this, arguments) || 0;
 | ||
|     };
 | ||
| 
 | ||
|     $.fn.safeOuterWidth = function () {
 | ||
|         return $(this).outerWidth.apply(this, arguments) || 0;
 | ||
|     };
 | ||
| 
 | ||
|     // For some reason, jQuery wants this to be attached to an element.
 | ||
|     $(document).ajaxError(function (event, xhr) {
 | ||
|         if (xhr.status === 401) {
 | ||
|             // We got logged out somehow, perhaps from another window or a session timeout.
 | ||
|             // We could display an error message, but jumping right to the login page seems
 | ||
|             // smoother and conveys the same information.
 | ||
|             window.location.replace(page_params.login_page);
 | ||
|         }
 | ||
|     });
 | ||
| 
 | ||
|     if (typeof $ !== 'undefined') {
 | ||
|         $.fn.expectOne = function () {
 | ||
|             if (blueslip && this.length !== 1) {
 | ||
|                 blueslip.error("Expected one element in jQuery set, " + this.length + " found");
 | ||
|             }
 | ||
|             return this;
 | ||
|         };
 | ||
| 
 | ||
|         $.fn.within = function (sel) {
 | ||
|             return $(this).is(sel) || $(this).closest(sel).length;
 | ||
|         };
 | ||
|     }
 | ||
| });
 |