diff --git a/jupyterhub/proxy.py b/jupyterhub/proxy.py index e7592ddc..91b9b75c 100644 --- a/jupyterhub/proxy.py +++ b/jupyterhub/proxy.py @@ -19,6 +19,7 @@ Route Specification: # Distributed under the terms of the Modified BSD License. import asyncio +from functools import wraps import json import os from subprocess import Popen @@ -41,6 +42,21 @@ from . import utils from .utils import url_path_join +def _one_at_a_time(method): + """decorator to limit an async method to be called only once + + If multiple concurrent calls to this method are made, + queue them instead of allowing them to be concurrently outstanding. + """ + method._lock = asyncio.Lock() + @wraps(method) + async def locked_method(*args, **kwargs): + async with method._lock: + return await method(*args, **kwargs) + + return locked_method + + class Proxy(LoggingConfigurable): """Base class for configurable proxies that JupyterHub can use. @@ -271,6 +287,7 @@ class Proxy(LoggingConfigurable): # wait after submitting them all await gen.multi(futures) + @_one_at_a_time async def check_routes(self, user_dict, service_dict, routes=None): """Check that all users are properly routed on the proxy.""" if not routes: