Przeglądaj źródła

Removes Autoreload feature completely

Ask Solem 8 lat temu
rodzic
commit
41873498ef

+ 0 - 1
celery/app/defaults.py

@@ -266,7 +266,6 @@ NAMESPACES = Namespace(
     worker=Namespace(
         __old__=OLD_NS_WORKER,
         agent=Option(None, type='string'),
-        autoreloader=Option('celery.worker.autoreload:Autoreloader'),
         concurrency=Option(0, type='int'),
         consumer=Option('celery.worker.consumer:Consumer', type='string'),
         direct=Option(False, type='bool', old={'celery_worker_direct'}),

+ 0 - 5
celery/bin/worker.py

@@ -119,10 +119,6 @@ The :program:`celery worker` command (previously known as ``celeryd``)
     completed and the child process will be replaced afterwards.
     Default: no limit.
 
-.. cmdoption:: --autoreload
-
-    Enable auto-reloading.
-
 .. cmdoption:: --no-execv
 
     Don't do execv after multiprocessing child fork.
@@ -322,7 +318,6 @@ class worker(Command):
         parser.add_option_group(qopts)
 
         fopts = OptionGroup(parser, 'Features')
-        fopts.add_option('--autoreload', action='store_true')
         fopts.add_option(
             '--without-gossip', action='store_true', default=False,
         )

+ 0 - 354
celery/tests/worker/test_autoreload.py

@@ -1,354 +0,0 @@
-from __future__ import absolute_import, unicode_literals
-
-import errno
-import select
-import sys
-
-from time import time
-
-from celery.worker import autoreload
-from celery.worker.autoreload import (
-    WorkerComponent,
-    file_hash,
-    BaseMonitor,
-    StatMonitor,
-    KQueueMonitor,
-    InotifyMonitor,
-    default_implementation,
-    Autoreloader,
-)
-
-from celery.tests.case import AppCase, Case, Mock, mock, patch
-
-
-class test_WorkerComponent(AppCase):
-
-    def test_create_threaded(self):
-        w = Mock()
-        w.use_eventloop = False
-        x = WorkerComponent(w)
-        x.instantiate = Mock()
-        r = x.create(w)
-        x.instantiate.assert_called_with(w.autoreloader_cls, w)
-        self.assertIs(r, w.autoreloader)
-
-    @patch('select.kevent', create=True)
-    @patch('select.kqueue', create=True)
-    @patch('kombu.utils.eventio.kqueue')
-    def test_create_ev(self, kq, kqueue, kevent):
-        w = Mock()
-        w.use_eventloop = True
-        x = WorkerComponent(w)
-        x.instantiate = Mock()
-        r = x.create(w)
-        x.instantiate.assert_called_with(w.autoreloader_cls, w)
-        x.register_with_event_loop(w, w.hub)
-        self.assertIsNone(r)
-        w.hub.on_close.add.assert_called_with(
-            w.autoreloader.on_event_loop_close,
-        )
-
-
-class test_file_hash(Case):
-
-    def test_hash(self):
-        with mock.open() as a:
-            a.write('the quick brown fox\n')
-            a.seek(0)
-            A = file_hash('foo')
-        with mock.open() as b:
-            b.write('the quick brown bar\n')
-            b.seek(0)
-            B = file_hash('bar')
-        self.assertNotEqual(A, B)
-
-
-class test_BaseMonitor(Case):
-
-    def test_start_stop_on_change(self):
-        x = BaseMonitor(['a', 'b'])
-
-        with self.assertRaises(NotImplementedError):
-            x.start()
-        x.stop()
-        x.on_change([])
-        x._on_change = Mock()
-        x.on_change('foo')
-        x._on_change.assert_called_with('foo')
-        x.on_event_loop_close(Mock())
-
-
-class test_StatMonitor(Case):
-
-    @patch('os.stat')
-    def test_start(self, stat):
-
-        class st(object):
-            st_mtime = time()
-        stat.return_value = st()
-        x = StatMonitor(['a', 'b'])
-
-        def on_is_set():
-            if x.shutdown_event.is_set.call_count > 3:
-                return True
-            return False
-        x.shutdown_event = Mock()
-        x.shutdown_event.is_set.side_effect = on_is_set
-
-        x.start()
-        x.shutdown_event = Mock()
-        stat.side_effect = OSError()
-        x.start()
-
-    def test_register_with_event_loop(self):
-        hub = Mock(name='hub')
-        x = StatMonitor(['a'])
-        x.register_with_event_loop(hub)
-        hub.call_repeatedly.assert_called_with(2.0, x.find_changes)
-
-    @patch('os.stat')
-    def test_mtime_stat_raises(self, stat):
-        stat.side_effect = ValueError()
-        x = StatMonitor(['a', 'b'])
-        x._mtime('a')
-
-
-class test_KQueueMonitor(Case):
-
-    @patch('select.kqueue', create=True)
-    @patch('os.close')
-    def test_stop(self, close, kqueue):
-        x = KQueueMonitor(['a', 'b'])
-        x.poller = Mock()
-        x.filemap['a'] = 10
-        x.stop()
-        x.poller.close.assert_called_with()
-        close.assert_called_with(10)
-
-        close.side_effect = OSError()
-        close.side_effect.errno = errno.EBADF
-        x.stop()
-
-    @patch('kombu.utils.eventio.kqueue', create=True)
-    def test_register_with_event_loop(self, kqueue):
-        x = KQueueMonitor(['a', 'b'])
-        hub = Mock(name='hub')
-        x.add_events = Mock(name='add_events()')
-        x.register_with_event_loop(hub)
-        x.add_events.assert_called_with(x._kq)
-        self.assertEqual(
-            x._kq.on_file_change,
-            x.handle_event,
-        )
-
-    def test_register_with_event_loop_no_kqueue(self):
-        from kombu.utils import eventio
-        prev, eventio.kqueue = eventio.kqueue, None
-        try:
-            x = KQueueMonitor(['a'])
-            x.register_with_event_loop(Mock())
-        finally:
-            eventio.kqueue = prev
-
-    def test_on_event_loop_close(self):
-        x = KQueueMonitor(['a', 'b'])
-        x.close = Mock()
-        x._kq = Mock(name='_kq')
-        x.on_event_loop_close(Mock(name='hub'))
-        x.close.assert_called_with(x._kq)
-
-    def test_handle_event(self):
-        x = KQueueMonitor(['a', 'b'])
-        x.on_change = Mock()
-        eA = Mock()
-        eA.ident = 'a'
-        eB = Mock()
-        eB.ident = 'b'
-        x.fdmap = {'a': 'A', 'b': 'B'}
-        x.handle_event([eA, eB])
-        x.on_change.assert_called_with(['A', 'B'])
-
-    @patch('kombu.utils.eventio.kqueue', create=True)
-    @patch('kombu.utils.eventio.kevent', create=True)
-    @patch('os.open')
-    @patch('select.kqueue', create=True)
-    def test_start(self, _kq, osopen, kevent, kqueue):
-        from kombu.utils import eventio
-        prev_poll, eventio.poll = eventio.poll, kqueue
-        prev = {}
-        flags = ['KQ_FILTER_VNODE', 'KQ_EV_ADD', 'KQ_EV_ENABLE',
-                 'KQ_EV_CLEAR', 'KQ_NOTE_WRITE', 'KQ_NOTE_EXTEND']
-        for i, flag in enumerate(flags):
-            prev[flag] = getattr(eventio, flag, None)
-            if not prev[flag]:
-                setattr(eventio, flag, i)
-        try:
-            kq = kqueue.return_value = Mock()
-
-            class ev(object):
-                ident = 10
-                filter = eventio.KQ_FILTER_VNODE
-            kq.control.return_value = [ev()]
-            x = KQueueMonitor(['a'])
-            osopen.return_value = 10
-            calls = [0]
-
-            def on_is_set():
-                calls[0] += 1
-                if calls[0] > 2:
-                    return True
-                return False
-            x.shutdown_event = Mock()
-            x.shutdown_event.is_set.side_effect = on_is_set
-            x.start()
-        finally:
-            for flag in flags:
-                if prev[flag]:
-                    setattr(eventio, flag, prev[flag])
-                else:
-                    delattr(eventio, flag)
-            eventio.poll = prev_poll
-
-
-class test_InotifyMonitor(Case):
-
-    @patch('celery.worker.autoreload.pyinotify')
-    def test_start(self, inotify):
-        x = InotifyMonitor(['a'])
-        inotify.IN_MODIFY = 1
-        inotify.IN_ATTRIB = 2
-        x.start()
-
-        inotify.WatchManager.side_effect = ValueError()
-        with self.assertRaises(ValueError):
-            x.start()
-        x.stop()
-
-        x._on_change = None
-        x.process_(Mock())
-        x._on_change = Mock()
-        x.process_(Mock())
-        x._on_change.assert_called()
-
-        x.create_notifier = Mock()
-        x._wm = Mock()
-        hub = Mock()
-        x.register_with_event_loop(hub)
-        x.create_notifier.assert_called_with()
-        hub.add_reader.assert_called_with(x._wm.get_fd(), x.on_readable)
-
-        x.on_event_loop_close(hub)
-        x._notifier = Mock()
-        x.on_readable()
-        x._notifier.read_events.assert_called_with()
-        x._notifier.process_events.assert_called_with()
-
-
-class test_default_implementation(Case):
-
-    @patch('select.kqueue', create=True)
-    @patch('kombu.utils.eventio.kqueue', create=True)
-    def test_kqueue(self, kq, kqueue):
-        self.assertEqual(default_implementation(), 'kqueue')
-
-    @patch('celery.worker.autoreload.pyinotify')
-    def test_inotify(self, pyinotify):
-        kq = getattr(select, 'kqueue', None)
-        try:
-            delattr(select, 'kqueue')
-        except AttributeError:
-            pass
-        platform, sys.platform = sys.platform, 'linux'
-        try:
-            self.assertEqual(default_implementation(), 'inotify')
-            ino, autoreload.pyinotify = autoreload.pyinotify, None
-            try:
-                self.assertEqual(default_implementation(), 'stat')
-            finally:
-                autoreload.pyinotify = ino
-        finally:
-            if kq:
-                select.kqueue = kq
-            sys.platform = platform
-
-
-class test_Autoreloader(AppCase):
-
-    def test_register_with_event_loop(self):
-        x = Autoreloader(Mock(), modules=[__name__])
-        hub = Mock()
-        x._monitor = None
-        x.on_init = Mock()
-
-        def se(*args, **kwargs):
-            x._monitor = Mock()
-        x.on_init.side_effect = se
-
-        x.register_with_event_loop(hub)
-        x.on_init.assert_called_with()
-        x._monitor.register_with_event_loop.assert_called_with(hub)
-
-        x._monitor.register_with_event_loop.reset_mock()
-        x.register_with_event_loop(hub)
-        x._monitor.register_with_event_loop.assert_called_with(hub)
-
-    def test_on_event_loop_close(self):
-        x = Autoreloader(Mock(), modules=[__name__])
-        hub = Mock()
-        x._monitor = Mock()
-        x.on_event_loop_close(hub)
-        x._monitor.on_event_loop_close.assert_called_with(hub)
-        x._monitor = None
-        x.on_event_loop_close(hub)
-
-    @patch('celery.worker.autoreload.file_hash')
-    def test_start(self, fhash):
-        x = Autoreloader(Mock(), modules=[__name__])
-        x.Monitor = Mock()
-        mon = x.Monitor.return_value = Mock()
-        mon.start.side_effect = OSError()
-        mon.start.side_effect.errno = errno.EINTR
-        x.body()
-        mon.start.side_effect.errno = errno.ENOENT
-        with self.assertRaises(OSError):
-            x.body()
-        mon.start.side_effect = None
-        x.body()
-
-    @patch('celery.worker.autoreload.file_hash')
-    @patch('os.path.exists')
-    def test_maybe_modified(self, exists, fhash):
-        exists.return_value = True
-        fhash.return_value = 'abcd'
-        x = Autoreloader(Mock(), modules=[__name__])
-        x._hashes = {}
-        x._hashes[__name__] = 'dcba'
-        self.assertTrue(x._maybe_modified(__name__))
-        x._hashes[__name__] = 'abcd'
-        self.assertFalse(x._maybe_modified(__name__))
-        exists.return_value = False
-        self.assertFalse(x._maybe_modified(__name__))
-
-    def test_on_change(self):
-        x = Autoreloader(Mock(), modules=[__name__])
-        mm = x._maybe_modified = Mock(0)
-        mm.return_value = True
-        x._reload = Mock()
-        x.file_to_module[__name__] = __name__
-        x.on_change([__name__])
-        x._reload.assert_called()
-        mm.return_value = False
-        x.on_change([__name__])
-
-    def test_reload(self):
-        x = Autoreloader(Mock(), modules=[__name__])
-        x._reload([__name__])
-        x.controller.reload.assert_called_with([__name__], reload=True)
-
-    def test_stop(self):
-        x = Autoreloader(Mock(), modules=[__name__])
-        x._monitor = None
-        x.stop()
-        x._monitor = Mock()
-        x.stop()
-        x._monitor.stop.assert_called_with()

+ 0 - 3
celery/worker/__init__.py

@@ -82,7 +82,6 @@ class WorkController(object):
             'celery.worker.components:Timer',
             'celery.worker.components:StateDB',
             'celery.worker.components:Consumer',
-            'celery.worker.autoreload:WorkerComponent',
         }
 
     def __init__(self, app=None, hostname=None, **kwargs):
@@ -341,7 +340,6 @@ class WorkController(object):
     def setup_defaults(self, concurrency=None, loglevel='WARN', logfile=None,
                        send_events=None, pool_cls=None, consumer_cls=None,
                        timer_cls=None, timer_precision=None,
-                       autoreloader_cls=None,
                        pool_putlocks=None, pool_restarts=None,
                        force_execv=None, state_db=None,
                        schedule_filename=None, scheduler_cls=None,
@@ -361,7 +359,6 @@ class WorkController(object):
         self.timer_precision = either(
             'worker_timer_precision', timer_precision,
         )
-        self.autoreloader_cls = either('worker_autoreloader', autoreloader_cls)
         self.pool_putlocks = either('worker_pool_putlocks', pool_putlocks)
         self.pool_restarts = either('worker_pool_restarts', pool_restarts)
         self.force_execv = either('worker_force_execv', force_execv)

+ 0 - 304
celery/worker/autoreload.py

@@ -1,304 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    ``celery.worker.autoreload``
-    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-    This module implements automatic module reloading
-
-"""
-from __future__ import absolute_import, unicode_literals
-
-import hashlib
-import os
-import select
-import sys
-import time
-
-from collections import defaultdict
-from threading import Event
-
-from kombu.utils import eventio
-from kombu.utils.encoding import ensure_bytes
-
-from celery import bootsteps
-from celery.five import items
-from celery.platforms import ignore_errno
-from celery.utils.imports import module_file
-from celery.utils.log import get_logger
-from celery.utils.threads import bgThread
-
-from .components import Pool
-
-try:                        # pragma: no cover
-    import pyinotify
-    _ProcessEvent = pyinotify.ProcessEvent
-except ImportError:         # pragma: no cover
-    pyinotify = None        # noqa
-    _ProcessEvent = object  # noqa
-
-__all__ = [
-    'WorkerComponent', 'Autoreloader', 'Monitor', 'BaseMonitor',
-    'StatMonitor', 'KQueueMonitor', 'InotifyMonitor', 'file_hash',
-]
-
-logger = get_logger(__name__)
-
-
-class WorkerComponent(bootsteps.StartStopStep):
-    label = 'Autoreloader'
-    conditional = True
-    requires = (Pool,)
-
-    def __init__(self, w, autoreload=None, **kwargs):
-        self.enabled = w.autoreload = autoreload
-        w.autoreloader = None
-
-    def create(self, w):
-        w.autoreloader = self.instantiate(w.autoreloader_cls, w)
-        return w.autoreloader if not w.use_eventloop else None
-
-    def register_with_event_loop(self, w, hub):
-        w.autoreloader.register_with_event_loop(hub)
-        hub.on_close.add(w.autoreloader.on_event_loop_close)
-
-
-def file_hash(filename, algorithm='md5'):
-    hobj = hashlib.new(algorithm)
-    with open(filename, 'rb') as f:
-        for chunk in iter(lambda: f.read(2 ** 20), ''):
-            hobj.update(ensure_bytes(chunk))
-    return hobj.digest()
-
-
-class BaseMonitor(object):
-
-    def __init__(self, files,
-                 on_change=None, shutdown_event=None, interval=0.5):
-        self.files = files
-        self.interval = interval
-        self._on_change = on_change
-        self.modify_times = defaultdict(int)
-        self.shutdown_event = shutdown_event or Event()
-
-    def start(self):
-        raise NotImplementedError('Subclass responsibility')
-
-    def stop(self):
-        pass
-
-    def on_change(self, modified):
-        if self._on_change:
-            return self._on_change(modified)
-
-    def on_event_loop_close(self, hub):
-        pass
-
-
-class StatMonitor(BaseMonitor):
-    """File change monitor based on the ``stat`` system call."""
-
-    def _mtimes(self):
-        return ((f, self._mtime(f)) for f in self.files)
-
-    def _maybe_modified(self, f, mt):
-        return mt is not None and self.modify_times[f] != mt
-
-    def register_with_event_loop(self, hub):
-        hub.call_repeatedly(2.0, self.find_changes)
-
-    def find_changes(self):
-        maybe_modified = self._maybe_modified
-        modified = {f: mt for f, mt in self._mtimes()
-                    if maybe_modified(f, mt)}
-        if modified:
-            self.on_change(modified)
-            self.modify_times.update(modified)
-
-    def start(self):
-        while not self.shutdown_event.is_set():
-            self.find_changes()
-            time.sleep(self.interval)
-
-    @staticmethod
-    def _mtime(path):
-        try:
-            return os.stat(path).st_mtime
-        except Exception:
-            pass
-
-
-class KQueueMonitor(BaseMonitor):
-    """File change monitor based on BSD kernel event notifications"""
-
-    def __init__(self, *args, **kwargs):
-        super(KQueueMonitor, self).__init__(*args, **kwargs)
-        self.filemap = {f: None for f in self.files}
-        self.fdmap = {}
-
-    def register_with_event_loop(self, hub):
-        if eventio.kqueue is not None:
-            self._kq = eventio._kqueue()
-            self.add_events(self._kq)
-            self._kq.on_file_change = self.handle_event
-            hub.add_reader(self._kq._kqueue, self._kq.poll, 0)
-
-    def on_event_loop_close(self, hub):
-        self.close(self._kq)
-
-    def add_events(self, poller):
-        for f in self.filemap:
-            self.filemap[f] = fd = os.open(f, os.O_RDONLY)
-            self.fdmap[fd] = f
-            poller.watch_file(fd)
-
-    def handle_event(self, events):
-        self.on_change([self.fdmap[e.ident] for e in events])
-
-    def start(self):
-        self.poller = eventio.poll()
-        self.add_events(self.poller)
-        self.poller.on_file_change = self.handle_event
-        while not self.shutdown_event.is_set():
-            self.poller.poll(1)
-
-    def close(self, poller):
-        for f, fd in items(self.filemap):
-            if fd is not None:
-                poller.unregister(fd)
-                with ignore_errno('EBADF'):  # pragma: no cover
-                    os.close(fd)
-        self.filemap.clear()
-        self.fdmap.clear()
-
-    def stop(self):
-        self.close(self.poller)
-        self.poller.close()
-
-
-class InotifyMonitor(_ProcessEvent):
-    """File change monitor based on Linux kernel `inotify` subsystem"""
-
-    def __init__(self, modules, on_change=None, **kwargs):
-        assert pyinotify
-        self._modules = modules
-        self._on_change = on_change
-        self._wm = None
-        self._notifier = None
-
-    def register_with_event_loop(self, hub):
-        self.create_notifier()
-        hub.add_reader(self._wm.get_fd(), self.on_readable)
-
-    def on_event_loop_close(self, hub):
-        pass
-
-    def on_readable(self):
-        self._notifier.read_events()
-        self._notifier.process_events()
-
-    def create_notifier(self):
-        self._wm = pyinotify.WatchManager()
-        self._notifier = pyinotify.Notifier(self._wm, self)
-        add_watch = self._wm.add_watch
-        flags = pyinotify.IN_MODIFY | pyinotify.IN_ATTRIB
-        for m in self._modules:
-            add_watch(m, flags)
-
-    def start(self):
-        try:
-            self.create_notifier()
-            self._notifier.loop()
-        finally:
-            if self._wm:
-                self._wm.close()
-                # Notifier.close is called at the end of Notifier.loop
-                self._wm = self._notifier = None
-
-    def stop(self):
-        pass
-
-    def process_(self, event):
-        self.on_change([event.path])
-
-    process_IN_ATTRIB = process_IN_MODIFY = process_
-
-    def on_change(self, modified):
-        if self._on_change:
-            return self._on_change(modified)
-
-
-def default_implementation():
-    if hasattr(select, 'kqueue') and eventio.kqueue is not None:
-        return 'kqueue'
-    elif sys.platform.startswith('linux') and pyinotify:
-        return 'inotify'
-    else:
-        return 'stat'
-
-implementations = {'kqueue': KQueueMonitor,
-                   'inotify': InotifyMonitor,
-                   'stat': StatMonitor}
-Monitor = implementations[
-    os.environ.get('CELERYD_FSNOTIFY') or default_implementation()]
-
-
-class Autoreloader(bgThread):
-    """Tracks changes in modules and fires reload commands"""
-    Monitor = Monitor
-
-    def __init__(self, controller, modules=None, monitor_cls=None, **options):
-        super(Autoreloader, self).__init__()
-        self.controller = controller
-        app = self.controller.app
-        self.modules = app.loader.task_modules if modules is None else modules
-        self.options = options
-        self._monitor = None
-        self._hashes = None
-        self.file_to_module = {}
-
-    def on_init(self):
-        files = self.file_to_module
-        files.update({
-            module_file(sys.modules[m]): m for m in self.modules
-        })
-
-        self._monitor = self.Monitor(
-            files, self.on_change,
-            shutdown_event=self._is_shutdown, **self.options)
-        self._hashes = {f: file_hash(f) for f in files}
-
-    def register_with_event_loop(self, hub):
-        if self._monitor is None:
-            self.on_init()
-        self._monitor.register_with_event_loop(hub)
-
-    def on_event_loop_close(self, hub):
-        if self._monitor is not None:
-            self._monitor.on_event_loop_close(hub)
-
-    def body(self):
-        self.on_init()
-        with ignore_errno('EINTR', 'EAGAIN'):
-            self._monitor.start()
-
-    def _maybe_modified(self, f):
-        if os.path.exists(f):
-            digest = file_hash(f)
-            if digest != self._hashes[f]:
-                self._hashes[f] = digest
-                return True
-        return False
-
-    def on_change(self, files):
-        modified = [f for f in files if self._maybe_modified(f)]
-        if modified:
-            names = [self.file_to_module[module] for module in modified]
-            logger.info('Detected modified modules: %r', names)
-            self._reload(names)
-
-    def _reload(self, modules):
-        self.controller.reload(modules, reload=True)
-
-    def stop(self):
-        if self._monitor:
-            self._monitor.stop()

+ 2 - 3
celery/worker/components.py

@@ -115,13 +115,12 @@ class Pool(bootsteps.StartStopStep):
     """
     requires = (Hub,)
 
-    def __init__(self, w, autoreload=None,
+    def __init__(self, w,
                  no_execv=False, optimization=None, **kwargs):
         w.pool = None
         w.max_concurrency = None
         w.min_concurrency = w.concurrency
         w.no_execv = no_execv
-        self.autoreload_enabled = autoreload
         self.optimization = optimization
 
     def close(self, w):
@@ -147,7 +146,7 @@ class Pool(bootsteps.StartStopStep):
             max_restarts = 100
             if w.pool_putlocks and w.pool_cls.uses_semaphore:
                 w.process_task = w._process_task_sem
-        allow_restart = self.autoreload_enabled or w.pool_restarts
+        allow_restart = w.pool_restarts
         pool = w.pool = self.instantiate(
             w.pool_cls, w.min_concurrency,
             initargs=(w.app, w.hostname),

+ 0 - 11
docs/configuration.rst

@@ -142,7 +142,6 @@ rush in moving to the new settings format.
 ``CELERYD_TASK_TIME_LIMIT``            :setting:`task_time_limit`
 ``CELERY_TRACK_STARTED``               :setting:`task_track_started`
 ``CELERYD_AGENT``                      :setting:`worker_agent`
-``CELERYD_AUTORELAODER``               :setting:`worker_autoreloader`
 ``CELERYD_CONCURRENCY``                :setting:`worker_concurrency`
 ``CELERYD_CONSUMER``                   :setting:`worker_consumer`
 ``CELERY_WORKER_DIRECT``               :setting:`worker_direct`
@@ -2230,16 +2229,6 @@ If enabled the worker pool can be restarted using the
 
 Disabled by default.
 
-.. setting:: worker_autoreloader
-
-``worker_autoreloader``
-~~~~~~~~~~~~~~~~~~~~~~~
-
-Name of the auto-reloader class used by the worker to reload
-Python modules and files that have changed.
-
-Default is: ``celery.worker.autoreload:Autoreloader``.
-
 .. setting:: worker_consumer
 
 ``worker_consumer``

+ 0 - 16
docs/getting-started/introduction.rst

@@ -183,22 +183,6 @@ Features
 
             :ref:`Read more… <guide-beat>`.
 
-        - **Autoreloading**
-
-            In development workers can be configured to automatically reload source
-            code as it changes, including :manpage:`inotify(7)` support on Linux.
-
-            :ref:`Read more… <worker-autoreloading>`.
-
-        - **Autoscaling**
-
-            Dynamically resizing the worker pool depending on load,
-            or custom metrics specified by the user, used to limit
-            memory usage in shared hosting/cloud environments or to
-            enforce a given quality of service.
-
-            :ref:`Read more… <worker-autoscaling>`.
-
         - **Resource Leak Protection**
 
             The :option:`--maxtasksperchild <celery worker --maxtasksperchild>`

+ 0 - 54
docs/history/whatsnew-2.5.rst

@@ -209,60 +209,6 @@ configuration to work (see :ref:`conf-security`).
 
 Contributed by Mher Movsisyan.
 
-Experimental support for automatic module reloading
----------------------------------------------------
-
-Starting :program:`celeryd` with the
-:option:`--autoreload <celery worker --autoreload>` option will
-enable the worker to watch for file system changes to all imported task
-modules imported (and also any non-task modules added to the
-:setting:`CELERY_IMPORTS` setting or the
-:option:`celery worker --include` option).
-
-This is an experimental feature intended for use in development only,
-using auto-reload in production is discouraged as the behavior of reloading
-a module in Python is undefined, and may cause hard to diagnose bugs and
-crashes.  Celery uses the same approach as the auto-reloader found in e.g.
-the Django ``runserver`` command.
-
-When auto-reload is enabled the worker starts an additional thread
-that watches for changes in the file system.  New modules are imported,
-and already imported modules are reloaded whenever a change is detected,
-and if the prefork pool is used the child processes will finish the work
-they are doing and exit, so that they can be replaced by fresh processes
-effectively reloading the code.
-
-File system notification backends are pluggable, and Celery comes with three
-implementations:
-
-* ``inotify`` (Linux)
-
-    Used if the :pypi:`pyinotify` library is installed.
-    If you are running on Linux this is the recommended implementation,
-    to install the :pypi:`pyinotify` library you have to run the following
-    command:
-
-    .. code-block:: console
-
-        $ pip install pyinotify
-
-* ``kqueue`` (macOS/BSD)
-
-* ``stat``
-
-    The fallback implementation simply polls the files using ``stat`` and is very
-    expensive.
-
-You can force an implementation by setting the :envvar:`CELERYD_FSNOTIFY`
-environment variable:
-
-.. code-block:: console
-
-    $ env CELERYD_FSNOTIFY=stat celeryd -l info --autoreload
-
-Contributed by Mher Movsisyan.
-
-
 New :setting:`CELERY_ANNOTATIONS` setting
 -----------------------------------------
 

+ 0 - 11
docs/internals/reference/celery.worker.autoreload.rst

@@ -1,11 +0,0 @@
-====================================
- ``celery.worker.autoreload``
-====================================
-
-.. contents::
-    :local:
-.. currentmodule:: celery.worker.autoreload
-
-.. automodule:: celery.worker.autoreload
-    :members:
-    :undoc-members:

+ 0 - 1
docs/internals/reference/index.rst

@@ -13,7 +13,6 @@
     celery.worker.heartbeat
     celery.worker.control
     celery.worker.pidbox
-    celery.worker.autoreload
     celery.concurrency
     celery.concurrency.solo
     celery.concurrency.prefork

+ 1 - 16
docs/userguide/extending.rst

@@ -205,21 +205,6 @@ Attributes
         class WorkerStep(bootsteps.StartStopStep):
             requires = ('celery.worker.components:Statedb',)
 
-.. _extending-worker-autoreloader:
-
-.. attribute:: autoreloader
-
-    :class:`~celery.worker.autoreloder.Autoreloader` used to automatically
-    reload use code when the file-system changes.
-
-    This is only defined if the ``autoreload`` argument is enabled.
-    Your worker bootstep must require the `Autoreloader` bootstep to use this;
-
-    .. code-block:: python
-
-        class WorkerStep(bootsteps.StartStopStep):
-            requires = ('celery.worker.autoreloader:Autoreloader',)
-
 Example worker bootstep
 -----------------------
 
@@ -653,7 +638,7 @@ will show us more information about the boot process:
     [2013-05-29 16:18:20,511: DEBUG/MainProcess] | Worker: Building graph...
     <celery.apps.worker.Worker object at 0x101ad8410> is in init
     [2013-05-29 16:18:20,511: DEBUG/MainProcess] | Worker: New boot order:
-        {Hub, Pool, Autoreloader, Timer, StateDB, InfoStep, Beat, Consumer}
+        {Hub, Pool, Timer, StateDB, InfoStep, Beat, Consumer}
     [2013-05-29 16:18:20,514: DEBUG/MainProcess] | Consumer: Preparing bootsteps.
     [2013-05-29 16:18:20,514: DEBUG/MainProcess] | Consumer: Building graph...
     <celery.worker.consumer.Consumer object at 0x101c2d8d0> is in init

+ 0 - 117
docs/userguide/workers.rst

@@ -699,123 +699,6 @@ This can also be done programmatically by using the
     >>> app.control.inspect(['worker1.local']).active_queues()
     [...]
 
-.. _worker-autoreloading:
-
-Auto-reloading
-==============
-
-.. versionadded:: 2.5
-
-:pool support: *prefork, eventlet, gevent, threads, solo*
-
-Starting :program:`celery worker` with the
-:option:`--autoreload <celery worker --autoreload>` option will
-enable the worker to watch for file system changes to all imported task
-modules (and also any non-task modules added to the :setting:`imports`
-setting or the :option:`--include <celery worker --include>` option).
-
-This is an experimental feature intended for use in development only,
-using auto-reload in production is discouraged as the behavior of reloading
-a module in Python is undefined, and may cause hard to diagnose bugs and
-crashes.  Celery uses the same approach as the auto-reloader found in e.g.
-the Django ``runserver`` command.
-
-When auto-reload is enabled the worker starts an additional thread
-that watches for changes in the file system.  New modules are imported,
-and already imported modules are reloaded whenever a change is detected,
-and if the prefork pool is used the child processes will finish the work
-they are doing and exit, so that they can be replaced by fresh processes
-effectively reloading the code.
-
-File system notification backends are pluggable, and it comes with three
-implementations:
-
-* ``inotify`` (Linux)
-
-    Used if the :pypi:`pyinotify` library is installed.
-    If you are running on Linux this is the recommended implementation,
-    to install the :pypi:`pyinotify` library you have to run the following
-    command:
-
-    .. code-block:: console
-
-        $ pip install pyinotify
-
-* ``kqueue`` (macOS/BSD)
-
-* ``stat``
-
-    The fallback implementation simply polls the files using ``stat`` and is very
-    expensive.
-
-You can force an implementation by setting the :envvar:`CELERYD_FSNOTIFY`
-environment variable:
-
-.. code-block:: console
-
-    $ env CELERYD_FSNOTIFY=stat celery worker -l info --autoreload
-
-.. _worker-autoreload:
-
-.. control:: pool_restart
-
-Pool Restart Command
---------------------
-
-.. versionadded:: 2.5
-
-Requires the :setting:`worker_pool_restarts` setting to be enabled.
-
-The remote control command :control:`pool_restart` sends restart requests to
-the workers child processes.  It is particularly useful for forcing
-the worker to import new modules, or for reloading already imported
-modules.  This command does not interrupt executing tasks.
-
-Example
-~~~~~~~
-
-Running the following command will result in the `foo` and `bar` modules
-being imported by the worker processes:
-
-.. code-block:: pycon
-
-    >>> app.control.broadcast('pool_restart',
-    ...                       arguments={'modules': ['foo', 'bar']})
-
-Use the ``reload`` argument to reload modules it has already imported:
-
-.. code-block:: pycon
-
-    >>> app.control.broadcast('pool_restart',
-    ...                       arguments={'modules': ['foo'],
-    ...                                  'reload': True})
-
-If you don't specify any modules then all known tasks modules will
-be imported/reloaded:
-
-.. code-block:: pycon
-
-    >>> app.control.broadcast('pool_restart', arguments={'reload': True})
-
-The ``modules`` argument is a list of modules to modify. ``reload``
-specifies whether to reload modules if they have previously been imported.
-By default ``reload`` is disabled. The `pool_restart` command uses the
-Python :func:`reload` function to reload modules, or you can provide
-your own custom reloader by passing the ``reloader`` argument.
-
-.. note::
-
-    Module reloading comes with caveats that are documented in :func:`reload`.
-    Please read this documentation and make sure your modules are suitable
-    for reloading.
-
-.. seealso::
-
-    - http://pyunit.sourceforge.net/notes/reloading.html
-    - http://www.indelible.org/ink/python-reloading/
-    - http://docs.python.org/library/functions.html#reload
-
-
 .. _worker-inspect:
 
 Inspecting workers

+ 1 - 1
extra/bash-completion/celery.bash

@@ -75,7 +75,7 @@ _celery()
         COMPREPLY=( $(compgen -W '--concurrency= --pool= --purge --logfile=
         --loglevel= --hostname= --beat --schedule= --scheduler= --statedb= --events
         --time-limit= --soft-time-limit= --maxtasksperchild= --queues=
-        --include= --pidfile= --autoreload --no-execv $fargs' -- ${cur} ) )
+        --include= --pidfile= --no-execv $fargs' -- ${cur} ) )
         return 0
         ;;
     inspect)

+ 0 - 1
extra/zsh-completion/celery.zsh

@@ -55,7 +55,6 @@ case "$words[1]" in
     '(-Q --queues=)'{-Q,--queues=}'[List of queues to enable for this worker, separated by comma. By default all configured queues are enabled.]' \
     '(-I --include=)'{-I,--include=}'[Comma separated list of additional modules to import.]' \
     '(--pidfile=)--pidfile=[Optional file used to store the process pid.]' \
-    '(--autoreload)--autoreload[Enable autoreloading.]' \
     '(--no-execv)--no-execv[Don"t do execv after multiprocessing child fork.]'
     compadd -a ifargs
     ;;