from __future__ import absolute_import

import logging

from functools import partial
from pprint import pformat

from tornado import websocket
from tornado.ioloop import PeriodicCallback

from ..models import WorkersModel
from ..settings import PAGE_UPDATE_INTERVAL


class UpdateWorkers(websocket.WebSocketHandler):
    listeners = []
    periodic_callback = None
    workers = None

    def open(self):
        app = self.application
        listeners = UpdateWorkers.listeners
        periodic_callback = UpdateWorkers.periodic_callback

        if not listeners:
            logging.debug('Starting a timer for dashboard updates')
            periodic_callback = periodic_callback or PeriodicCallback(
                partial(UpdateWorkers.on_update_time, app),
                PAGE_UPDATE_INTERVAL)
            periodic_callback.start()
        listeners.append(self)

    def on_message(self, message):
        pass

    def on_close(self):
        listeners = UpdateWorkers.listeners
        periodic_callback = UpdateWorkers.periodic_callback

        listeners.remove(self)
        if not listeners and periodic_callback:
            logging.debug('Stopping dashboard updates timer')
            periodic_callback.stop()

    @classmethod
    def on_update_time(cls, app):
        workers = WorkersModel.get_latest(app)
        changes = workers.workers

        if workers != cls.workers and changes:
            logging.debug('Sending dashboard updates: %s', pformat(changes))
            for l in cls.listeners:
                l.write_message(changes)
            cls.workers = workers

from __future__ import absolute_import

import logging

from functools import partial
from pprint import pformat

from tornado import websocket
from tornado.ioloop import PeriodicCallback

from ..models import WorkersModel
from ..settings import PAGE_UPDATE_INTERVAL


class UpdateWorkers(websocket.WebSocketHandler):
    listeners = []
    periodic_callback = None
    workers = None

    def open(self):
        app = self.application
        listeners = UpdateWorkers.listeners
        periodic_callback = UpdateWorkers.periodic_callback

        if not listeners:
            logging.debug('Starting a timer for dashboard updates')
            periodic_callback = periodic_callback or PeriodicCallback(
                partial(UpdateWorkers.on_update_time, app),
                PAGE_UPDATE_INTERVAL)
            if not periodic_callback._running:
                periodic_callback.start()
        listeners.append(self)

    def on_message(self, message):
        pass

    def on_close(self):
        listeners = UpdateWorkers.listeners
        periodic_callback = UpdateWorkers.periodic_callback

        listeners.remove(self)
        if not listeners and periodic_callback:
            logging.debug('Stopping dashboard updates timer')
            periodic_callback.stop()

    @classmethod
    def on_update_time(cls, app):
        workers = WorkersModel.get_latest(app)
        changes = workers.workers

        if workers != cls.workers and changes:
            logging.debug('Sending dashboard updates: %s', pformat(changes))
            for l in cls.listeners:
                l.write_message(changes)
            cls.workers = workers

Make sure workers status updater is not running before starting it. on_close may not be called by some browsers