|
1 | 1 | import json |
2 | 2 | from concurrent.futures import ThreadPoolExecutor |
| 3 | +from inspect import isawaitable |
3 | 4 |
|
4 | 5 | import psutil |
5 | | -import zmq |
| 6 | +import zmq.asyncio |
6 | 7 | from jupyter_client.jsonutil import date_default |
7 | 8 | from jupyter_server.base.handlers import APIHandler |
8 | | -from jupyter_server.utils import url_path_join |
9 | 9 | from packaging import version |
10 | 10 | from tornado import web |
11 | 11 | from tornado.concurrent import run_on_executor |
12 | 12 |
|
13 | | -try: |
14 | | - # Traitlets >= 4.3.3 |
15 | | - from traitlets import Callable |
16 | | -except ImportError: |
17 | | - from .utils import Callable |
18 | | - |
19 | 13 |
|
20 | 14 | try: |
21 | 15 | import ipykernel |
|
24 | 18 | except ImportError: |
25 | 19 | USAGE_IS_SUPPORTED = False |
26 | 20 |
|
27 | | -MAX_RETRIES = 3 |
28 | | - |
29 | 21 |
|
30 | 22 | class ApiHandler(APIHandler): |
31 | 23 | executor = ThreadPoolExecutor(max_workers=5) |
@@ -113,17 +105,18 @@ async def get(self, matched_part=None, *args, **kwargs): |
113 | 105 | usage_request = session.msg("usage_request", {}) |
114 | 106 |
|
115 | 107 | control_channel.send(usage_request) |
116 | | - poller = zmq.Poller() |
| 108 | + poller = zmq.asyncio.Poller() |
117 | 109 | control_socket = control_channel.socket |
118 | 110 | poller.register(control_socket, zmq.POLLIN) |
119 | | - for i in range(1, MAX_RETRIES + 1): |
120 | | - timeout_ms = 1000 * i |
121 | | - events = dict(poller.poll(timeout_ms)) |
122 | | - if not events: |
123 | | - self.write(json.dumps({})) |
124 | | - break |
125 | | - if control_socket not in events: |
126 | | - continue |
127 | | - res = await client.control_channel.get_msg(timeout=0) |
| 111 | + # previous behavior was 3 retries: 1 + 2 + 3 = 6 seconds |
| 112 | + timeout_ms = 6_000 |
| 113 | + events = dict(await poller.poll(timeout_ms)) |
| 114 | + if control_socket not in events: |
| 115 | + self.write(json.dumps({})) |
| 116 | + else: |
| 117 | + res = client.control_channel.get_msg(timeout=0) |
| 118 | + if isawaitable(res): |
| 119 | + # control_channel.get_msg may return a Future, |
| 120 | + # depending on configured KernelManager class |
| 121 | + res = await res |
128 | 122 | self.write(json.dumps(res, default=date_default)) |
129 | | - break |
0 commit comments