summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacob Green <jacob@workflowy.com>2019-04-23 09:08:05 -0700
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2019-04-26 13:35:47 +0200
commite45763193fe496cefc6749c45e6a31e62f987d63 (patch)
tree14f54f837c9a4667f6d1b1085693cf0ca607c875
parenta4095dadc4b165f615dfc88c6ed1cbba5b5a9844 (diff)
[2.2.x] Fixed #30361 -- Increased the default timeout of watchman client to 5 seconds and made it customizable.
Made the default timeout of watchman client customizable via DJANGO_WATCHMAN_TIMEOUT environment variable. Backport of ed3c59097a01ed3f32f8a8bed95307fb5c181251 from master
-rw-r--r--AUTHORS1
-rw-r--r--django/utils/autoreload.py5
-rw-r--r--docs/ref/django-admin.txt5
-rw-r--r--docs/releases/2.2.1.txt4
-rw-r--r--tests/utils_tests/test_autoreload.py9
5 files changed, 22 insertions, 2 deletions
diff --git a/AUTHORS b/AUTHORS
index bdeb2f5925..992e1d9f99 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -359,6 +359,7 @@ answer newbie questions, and generally made Django that much better:
Jaap Roes <jaap.roes@gmail.com>
Jack Moffitt <https://metajack.im/>
Jacob Burch <jacobburch@gmail.com>
+ Jacob Green
Jacob Kaplan-Moss <jacob@jacobian.org>
Jakub Paczkowski <jakub@paczkowski.eu>
Jakub Wilk <jwilk@jwilk.net>
diff --git a/django/utils/autoreload.py b/django/utils/autoreload.py
index 33f2b2be96..d43342c2d7 100644
--- a/django/utils/autoreload.py
+++ b/django/utils/autoreload.py
@@ -366,11 +366,12 @@ class WatchmanReloader(BaseReloader):
def __init__(self):
self.roots = defaultdict(set)
self.processed_request = threading.Event()
+ self.client_timeout = int(os.environ.get('DJANGO_WATCHMAN_TIMEOUT', 5))
super().__init__()
@cached_property
def client(self):
- return pywatchman.client()
+ return pywatchman.client(timeout=self.client_timeout)
def _watch_root(self, root):
# In practice this shouldn't occur, however, it's possible that a
@@ -528,7 +529,7 @@ class WatchmanReloader(BaseReloader):
def check_availability(cls):
if not pywatchman:
raise WatchmanUnavailable('pywatchman not installed.')
- client = pywatchman.client(timeout=0.01)
+ client = pywatchman.client(timeout=0.1)
try:
result = client.capabilityCheck()
except Exception:
diff --git a/docs/ref/django-admin.txt b/docs/ref/django-admin.txt
index 582eabdd3b..80a4303509 100644
--- a/docs/ref/django-admin.txt
+++ b/docs/ref/django-admin.txt
@@ -888,6 +888,11 @@ more robust change detection, and a reduction in power usage.
for optimal performance. See the `watchman documentation`_ for information
on how to do this.
+.. admonition:: Watchman timeout
+
+ The default timeout of ``Watchman`` client is 5 seconds. You can change it
+ by setting the ``DJANGO_WATCHMAN_TIMEOUT`` environment variable.
+
.. _Watchman: https://facebook.github.io/watchman/
.. _pywatchman: https://pypi.org/project/pywatchman/
.. _watchman documentation: https://facebook.github.io/watchman/docs/config.html#ignore_dirs
diff --git a/docs/releases/2.2.1.txt b/docs/releases/2.2.1.txt
index b7b1f6112d..98f800d455 100644
--- a/docs/releases/2.2.1.txt
+++ b/docs/releases/2.2.1.txt
@@ -55,3 +55,7 @@ Bugfixes
:class:`~django.contrib.sessions.middleware.SessionMiddleware` subclasses,
rather than requiring :mod:`django.contrib.sessions` to be in
:setting:`INSTALLED_APPS` (:ticket:`30312`).
+
+* Increased the default timeout when using ``Watchman`` to 5 seconds to prevent
+ falling back to ``StatReloader`` on larger projects and made it customizable
+ via the ``DJANGO_WATCHMAN_TIMEOUT`` environment variable (:ticket:`30361`).
diff --git a/tests/utils_tests/test_autoreload.py b/tests/utils_tests/test_autoreload.py
index 1f3bc0c95b..f47ad46b8b 100644
--- a/tests/utils_tests/test_autoreload.py
+++ b/tests/utils_tests/test_autoreload.py
@@ -556,6 +556,11 @@ def skip_unless_watchman_available():
class WatchmanReloaderTests(ReloaderTests, IntegrationTests):
RELOADER_CLS = autoreload.WatchmanReloader
+ def setUp(self):
+ super().setUp()
+ # Shorten the timeout to speed up tests.
+ self.reloader.client_timeout = 0.1
+
def test_watch_glob_ignores_non_existing_directories_two_levels(self):
with mock.patch.object(self.reloader, '_subscribe') as mocked_subscribe:
self.reloader._watch_glob(self.tempdir / 'does_not_exist' / 'more', ['*'])
@@ -636,6 +641,10 @@ class WatchmanReloaderTests(ReloaderTests, IntegrationTests):
self.reloader.update_watches()
self.assertIsInstance(mocked_server_status.call_args[0][0], TestException)
+ @mock.patch.dict(os.environ, {'DJANGO_WATCHMAN_TIMEOUT': '10'})
+ def test_setting_timeout_from_environment_variable(self):
+ self.assertEqual(self.RELOADER_CLS.client_timeout, 10)
+
class StatReloaderTests(ReloaderTests, IntegrationTests):
RELOADER_CLS = autoreload.StatReloader