Skip to content

Commit 34e1ead

Browse files
author
Akshay Chitneni
committed
Ability to configure cull_idle_timeout with kernelSpec
1 parent 393c108 commit 34e1ead

File tree

2 files changed

+43
-1
lines changed

2 files changed

+43
-1
lines changed

jupyter_server/services/kernels/kernelmanager.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -645,6 +645,9 @@ async def cull_kernel_if_idle(self, kernel_id):
645645
await ensure_async(self.shutdown_kernel(kernel_id))
646646
return
647647

648+
kernel_spec_metadata = kernel.kernel_spec.metadata
649+
cull_idle_timeout = kernel_spec_metadata.get("cull_idle_timeout", self.cull_idle_timeout)
650+
648651
if hasattr(
649652
kernel, "last_activity"
650653
): # last_activity is monkey-patched, so ensure that has occurred
@@ -657,7 +660,7 @@ async def cull_kernel_if_idle(self, kernel_id):
657660
dt_now = utcnow()
658661
dt_idle = dt_now - kernel.last_activity
659662
# Compute idle properties
660-
is_idle_time = dt_idle > timedelta(seconds=self.cull_idle_timeout)
663+
is_idle_time = dt_idle > timedelta(seconds=cull_idle_timeout)
661664
is_idle_execute = self.cull_busy or (kernel.execution_state != "busy")
662665
connections = self._kernel_connections.get(kernel_id, 0)
663666
is_idle_connected = self.cull_connected or not connections

tests/services/kernels/test_cull.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@
1212
CULL_TIMEOUT = 30 if platform.python_implementation() == "PyPy" else 5
1313
CULL_INTERVAL = 1
1414

15+
sample_kernel_json_with_metadata = {
16+
"argv": ["cat", "{connection_file}"],
17+
"display_name": "Test kernel",
18+
"metadata": {"cull_idle_timeout": 0},
19+
}
20+
1521

1622
@pytest.fixture(autouse=True)
1723
def suppress_deprecation_warnings():
@@ -24,6 +30,21 @@ def suppress_deprecation_warnings():
2430
yield
2531

2632

33+
@pytest.fixture
34+
def jp_kernelspec_with_metadata(jp_data_dir):
35+
"""Configures some sample kernelspecs in the Jupyter data directory."""
36+
kenrel_spec_name = "sample_with_metadata"
37+
sample_kernel_dir = jp_data_dir.joinpath("kernels", kenrel_spec_name)
38+
sample_kernel_dir.mkdir(parents=True)
39+
# Create kernel json file
40+
sample_kernel_file = sample_kernel_dir.joinpath("kernel.json")
41+
kernel_json = sample_kernel_json_with_metadata.copy()
42+
sample_kernel_file.write_text(json.dumps(kernel_json))
43+
# Create resources text
44+
sample_kernel_resources = sample_kernel_dir.joinpath("resource.txt")
45+
sample_kernel_resources.write_text("resource")
46+
47+
2748
@pytest.mark.parametrize(
2849
"jp_server_config",
2950
[
@@ -73,6 +94,24 @@ async def test_cull_idle(jp_fetch, jp_ws_fetch):
7394
assert culled
7495

7596

97+
async def test_cull_idle_disable(jp_fetch, jp_ws_fetch, jp_kernelspec_with_metadata):
98+
r = await jp_fetch("api", "kernels", method="POST", allow_nonstandard_methods=True)
99+
kernel = json.loads(r.body.decode())
100+
kid = kernel["id"]
101+
102+
# Open a websocket connection.
103+
ws = await jp_ws_fetch("api", "kernels", kid, "channels")
104+
105+
r = await jp_fetch("api", "kernels", kid, method="GET")
106+
model = json.loads(r.body.decode())
107+
assert model["connections"] == 1
108+
culled = await get_cull_status(kid, jp_fetch) # connected, should not be culled
109+
assert not culled
110+
ws.close()
111+
culled = await get_cull_status(kid, jp_fetch) # not connected, should not be culled
112+
assert not culled
113+
114+
76115
# Pending kernels was released in Jupyter Client 7.1
77116
# It is currently broken on Windows (Jan 2022). When fixed, we can remove the Windows check.
78117
# See https://github.com/jupyter-server/jupyter_server/issues/672

0 commit comments

Comments
 (0)