import Queue
import threading
import websocket
import json
import time

def _run_worker():
    while True:
        _, fn, args = _work_queue.get()
        try:
            fn(*args)
        except:
            pass

_work_queue = Queue.PriorityQueue()
_worker_thread = threading.Thread(target=_run_worker)
_worker_thread.daemon = True
_worker_thread.start()

def queue_work(priority, fn, *args):
    _work_queue.put((-priority, fn, args))


def _run_socket():
    global _websocket
    while True:
        try:
            _websocket = websocket.create_connection('wss://socket.lichess.org/api/socket')
            with _games_lock:
                for game_id in _games.keys():
                    _start_watching(game_id)
            while True:
                msg = json.loads(_websocket.recv())
                if msg['t'] == 'fen':
                    with _games_lock:
                        game_id = msg['d']['id']
                        if game_id in _games:
                            _games[game_id] = msg
        except:
            time.sleep(1)

def _start_watching(game_id):
    try:
        _websocket.send(json.dumps({'t': 'startWatching', 'd': game_id}))
    except:
        pass

_websocket = None
_games = {}
_games_lock = threading.Lock()
_socket_thread = threading.Thread(target=_run_socket)
_socket_thread.daemon = True
_socket_thread.start()

def watch_games(game_ids):
    with _games_lock:
        game_id_set = set(game_ids)
        for game_id in set(_games.keys()) - game_id_set:
            del _games[game_id]
        for game_id in game_id_set - set(_games.keys()):
            _games[game_id] = None
            _start_watching(game_id)
        return [_games[game_id] for game_id in game_ids]

def add_watch(game_id):
    with _games_lock:
        if game_id not in _games:
            _games[game_id] = None
            _start_watching(game_id)

import Queue
import threading
import websocket
import json
import time
from django.utils import timezone
from datetime import timedelta

def _run_worker():
    while True:
        _, fn, args = _work_queue.get()
        try:
            fn(*args)
        except:
            pass

_work_queue = Queue.PriorityQueue()
_worker_thread = threading.Thread(target=_run_worker)
_worker_thread.daemon = True
_worker_thread.start()

def queue_work(priority, fn, *args):
    _work_queue.put((-priority, fn, args))


def _run_socket():
    global _websocket
    last_start = None
    while True:
        try:
            if last_start is not None and last_start > timezone.now() - timedelta(seconds=10):
                time.sleep(1)
            last_start = timezone.now()

            _websocket = websocket.create_connection('wss://socket.lichess.org/api/socket')
            with _games_lock:
                for game_id in _games.keys():
                    _start_watching(game_id)
            while True:
                msg = json.loads(_websocket.recv())
                if msg['t'] == 'fen':
                    with _games_lock:
                        game_id = msg['d']['id']
                        if game_id in _games:
                            _games[game_id] = msg
        except:
            continue

def _start_watching(game_id):
    try:
        _websocket.send(json.dumps({'t': 'startWatching', 'd': game_id}))
    except:
        pass

_websocket = None
_games = {}
_games_lock = threading.Lock()
_socket_thread = threading.Thread(target=_run_socket)
_socket_thread.daemon = True
_socket_thread.start()

def watch_games(game_ids):
    with _games_lock:
        game_id_set = set(game_ids)
        for game_id in set(_games.keys()) - game_id_set:
            del _games[game_id]
        for game_id in game_id_set - set(_games.keys()):
            _games[game_id] = None
            _start_watching(game_id)
        return [_games[game_id] for game_id in game_ids]

def add_watch(game_id):
    with _games_lock:
        if game_id not in _games:
            _games[game_id] = None
            _start_watching(game_id)

Improve TV socket client uptime