From 65923c94ef32de72320f031d954b335eb74d540c Mon Sep 17 00:00:00 2001 From: JackDandy Date: Sat, 28 Apr 2018 15:57:04 +0100 Subject: [PATCH] =?UTF-8?q?Update=20Tornado=20Web=20Server=205.0.1=20(35a5?= =?UTF-8?q?38f)=20=E2=86=92=205.0.1=20(2b2a220a).?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGES.md | 1 + lib/tornado/ioloop.py | 18 +++++++++++++++++- lib/tornado/web.py | 1 + lib/tornado/websocket.py | 18 +++++------------- 4 files changed, 24 insertions(+), 14 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 5f4ac222..faf1a9d2 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,6 @@ ### 0.17.0 (2018-xx-xx xx:xx:xx UTC) +* Update Tornado Web Server 5.0.1 (35a538f) to 5.0.1 (2b2a220a) [develop changelog] diff --git a/lib/tornado/ioloop.py b/lib/tornado/ioloop.py index 48700139..123f2ba5 100644 --- a/lib/tornado/ioloop.py +++ b/lib/tornado/ioloop.py @@ -47,6 +47,7 @@ import threading import time import traceback import math +import random from tornado.concurrent import Future, is_future, chain_future, future_set_exc_info, future_add_done_callback # noqa: E501 from tornado.log import app_log, gen_log @@ -1161,6 +1162,14 @@ class PeriodicCallback(object): Note that the timeout is given in milliseconds, while most other time-related functions in Tornado use seconds. + If ``jitter`` is specified, each callback time will be randomly selected + within a window of ``jitter * callback_time`` milliseconds. + Jitter can be used to reduce alignment of events with similar periods. + A jitter of 0.1 means allowing a 10% variation in callback time. + The window is centered on ``callback_time`` so the total number of calls + within a given interval should not be significantly affected by adding + jitter. + If the callback runs for longer than ``callback_time`` milliseconds, subsequent invocations will be skipped to get back on schedule. @@ -1168,12 +1177,16 @@ class PeriodicCallback(object): .. versionchanged:: 5.0 The ``io_loop`` argument (deprecated since version 4.1) has been removed. + + .. versionchanged:: 5.1 + The ``jitter`` argument is added. """ - def __init__(self, callback, callback_time): + def __init__(self, callback, callback_time, jitter=0): self.callback = callback if callback_time <= 0: raise ValueError("Periodic callback must have a positive callback_time") self.callback_time = callback_time + self.jitter = jitter self._running = False self._timeout = None @@ -1218,6 +1231,9 @@ class PeriodicCallback(object): def _update_next(self, current_time): callback_time_sec = self.callback_time / 1000.0 + if self.jitter: + # apply jitter fraction + callback_time_sec *= 1 + (self.jitter * (random.random() - 0.5)) if self._next_timeout <= current_time: # The period should be measured from the start of one call # to the start of the next. If one call takes too long, diff --git a/lib/tornado/web.py b/lib/tornado/web.py index 8a9a8053..4f427729 100644 --- a/lib/tornado/web.py +++ b/lib/tornado/web.py @@ -2825,6 +2825,7 @@ class FallbackHandler(RequestHandler): def prepare(self): self.fallback(self.request) self._finished = True + self.on_finish() class OutputTransform(object): diff --git a/lib/tornado/websocket.py b/lib/tornado/websocket.py index 91c5f1ff..738a9ccb 100644 --- a/lib/tornado/websocket.py +++ b/lib/tornado/websocket.py @@ -19,7 +19,6 @@ the protocol (known as "draft 76") and are not compatible with this module. from __future__ import absolute_import, division, print_function import base64 -import collections import hashlib import os import struct @@ -34,6 +33,7 @@ from tornado.ioloop import IOLoop, PeriodicCallback from tornado.iostream import StreamClosedError from tornado.log import gen_log, app_log from tornado import simple_httpclient +from tornado.queues import Queue from tornado.tcpclient import TCPClient from tornado.util import _websocket_mask, PY3 @@ -1096,8 +1096,7 @@ class WebSocketClientConnection(simple_httpclient._HTTPConnection): self.compression_options = compression_options self.connect_future = Future() self.protocol = None - self.read_future = None - self.read_queue = collections.deque() + self.read_queue = Queue(1) self.key = base64.b64encode(os.urandom(16)) self._on_message_callback = on_message_callback self.close_code = self.close_reason = None @@ -1207,12 +1206,8 @@ class WebSocketClientConnection(simple_httpclient._HTTPConnection): is given it will be called with the future when it is ready. """ - assert self.read_future is None - future = Future() - if self.read_queue: - future_set_result_unless_cancelled(future, self.read_queue.popleft()) - else: - self.read_future = future + + future = self.read_queue.get() if callback is not None: self.io_loop.add_future(future, callback) return future @@ -1220,11 +1215,8 @@ class WebSocketClientConnection(simple_httpclient._HTTPConnection): def on_message(self, message): if self._on_message_callback: self._on_message_callback(message) - elif self.read_future is not None: - future_set_result_unless_cancelled(self.read_future, message) - self.read_future = None else: - self.read_queue.append(message) + return self.read_queue.put(message) def ping(self, data=b''): """Send ping frame to the remote end.