From 709c3b50fcba333740bb337bac69a801dbbdc4ee Mon Sep 17 00:00:00 2001 From: Greg Price Date: Thu, 20 Jul 2017 17:20:31 -0700 Subject: [PATCH] tornado: Use a machine-readable error code when an event queue is gone. This fixes the original issue that #5598 was the root cause of; when the user returns to a Zulip browser tab after they've been idle past the timeout (10 min, per IDLE_EVENT_QUEUE_TIMEOUT_SECS), we now correctly reload the page even if they're using Zulip in German or another non-English language where we have a translation for the relevant error message. --- static/js/server_events.js | 2 +- zerver/lib/exceptions.py | 1 + zerver/tornado/event_queue.py | 3 ++- zerver/tornado/exceptions.py | 19 +++++++++++++++++++ zerver/tornado/socket.py | 3 ++- zerver/tornado/views.py | 3 ++- 6 files changed, 27 insertions(+), 4 deletions(-) create mode 100644 zerver/tornado/exceptions.py diff --git a/static/js/server_events.js b/static/js/server_events.js index 1589b419f2..ee3636adb9 100644 --- a/static/js/server_events.js +++ b/static/js/server_events.js @@ -188,7 +188,7 @@ function get_events(options) { // If we're old enough that our message queue has been // garbage collected, immediately reload. if ((xhr.status === 400) && - (JSON.parse(xhr.responseText).msg.indexOf("Bad event queue id") !== -1)) { + (JSON.parse(xhr.responseText).code === 'BAD_EVENT_QUEUE_ID')) { page_params.event_queue_expired = true; reload.initiate({immediate: true, save_pointer: false, diff --git a/zerver/lib/exceptions.py b/zerver/lib/exceptions.py index c631bee40c..336ca0df33 100644 --- a/zerver/lib/exceptions.py +++ b/zerver/lib/exceptions.py @@ -35,6 +35,7 @@ class ErrorCode(AbstractEnum): QUOTA_EXCEEDED = () BAD_NARROW = () UNAUTHORIZED_PRINCIPAL = () + BAD_EVENT_QUEUE_ID = () class JsonableError(Exception): '''A standardized error format we can turn into a nice JSON HTTP response. diff --git a/zerver/tornado/event_queue.py b/zerver/tornado/event_queue.py index 9736bc9b08..9f31b68559 100644 --- a/zerver/tornado/event_queue.py +++ b/zerver/tornado/event_queue.py @@ -33,6 +33,7 @@ from zerver.lib.queue import queue_json_publish from zerver.lib.request import JsonableError from zerver.lib.timestamp import timestamp_to_datetime from zerver.tornado.descriptors import clear_descriptor_by_handler_id, set_descriptor_by_handler_id +from zerver.tornado.exceptions import BadEventQueueIdError import copy import six @@ -513,7 +514,7 @@ def fetch_events(query): raise JsonableError(_("Missing 'last_event_id' argument")) client = get_client_descriptor(queue_id) if client is None: - raise JsonableError(_("Bad event queue id: %s") % (queue_id,)) + raise BadEventQueueIdError(queue_id) if user_profile_id != client.user_profile_id: raise JsonableError(_("You are not authorized to get events from this queue")) client.event_queue.prune(last_event_id) diff --git a/zerver/tornado/exceptions.py b/zerver/tornado/exceptions.py new file mode 100644 index 0000000000..7a0107c372 --- /dev/null +++ b/zerver/tornado/exceptions.py @@ -0,0 +1,19 @@ +from __future__ import absolute_import +from typing import Text + +from django.utils.translation import ugettext as _ + +from zerver.lib.exceptions import JsonableError, ErrorCode + +class BadEventQueueIdError(JsonableError): + code = ErrorCode.BAD_EVENT_QUEUE_ID + data_fields = ['queue_id'] + + def __init__(self, queue_id): + # type: (Text) -> None + self.queue_id = queue_id # type: Text + + @staticmethod + def msg_format(): + # type: () -> Text + return _("Bad event queue id: {queue_id}") diff --git a/zerver/tornado/socket.py b/zerver/tornado/socket.py index c45c986a53..03bc107fda 100644 --- a/zerver/tornado/socket.py +++ b/zerver/tornado/socket.py @@ -31,6 +31,7 @@ from zerver.middleware import record_request_start_data, record_request_stop_dat from zerver.lib.redis_utils import get_redis_client from zerver.lib.sessions import get_session_user from zerver.tornado.event_queue import get_client_descriptor +from zerver.tornado.exceptions import BadEventQueueIdError logger = logging.getLogger('zulip.socket') @@ -137,7 +138,7 @@ class SocketConnection(sockjs.tornado.SockJSConnection): queue_id = msg['request']['queue_id'] client = get_client_descriptor(queue_id) if client is None: - raise JsonableError(_('Bad event queue id: %s') % (queue_id,)) + raise BadEventQueueIdError(queue_id) if user_profile.id != client.user_profile_id: raise JsonableError(_("You are not the owner of the queue with id '%s'") % (queue_id,)) diff --git a/zerver/tornado/views.py b/zerver/tornado/views.py index 0c37ffc1bd..6d756785f5 100644 --- a/zerver/tornado/views.py +++ b/zerver/tornado/views.py @@ -13,6 +13,7 @@ from zerver.lib.response import json_success, json_error, json_response_from_err from zerver.lib.validator import check_bool, check_list, check_string from zerver.tornado.event_queue import get_client_descriptor, \ process_notification, fetch_events +from zerver.tornado.exceptions import BadEventQueueIdError from django.core.handlers.base import BaseHandler from typing import Union, Optional, Iterable, Sequence, List, Text @@ -30,7 +31,7 @@ def cleanup_event_queue(request, user_profile, queue_id=REQ()): # type: (HttpRequest, UserProfile, Text) -> HttpResponse client = get_client_descriptor(str(queue_id)) if client is None: - return json_error(_("Bad event queue id: %s") % (queue_id,)) + return json_response_from_error(BadEventQueueIdError(queue_id)) if user_profile.id != client.user_profile_id: return json_error(_("You are not authorized to access this queue")) request._log_data['extra'] = "[%s]" % (queue_id,)