11"""Manager for jupyter server proxy"""
22
3- from collections import namedtuple
4-
5- from jupyter_server .utils import url_path_join as ujoin
6- from tornado .ioloop import PeriodicCallback
7-
8- from .utils import check_pid
9-
10- ServerProxy = namedtuple ("ServerProxy" , ["name" , "url" , "cmd" , "port" , "managed" ])
11- ServerProxyProc = namedtuple ("ServerProxyProc" , ["name" , "proc" ])
3+ import asyncio
124
5+ from collections import namedtuple
136
14- async def monitor_server_proxy_procs ():
15- """Perodically monitor the server proxy processes. If user terminates
16- the process outside of jupyter-server-proxy, we should be able to
17- capture that and remove proxy app from manager"""
18- # Get current active apps
19- procs = manager ._list_server_proxy_procs ()
7+ from traitlets import List , Int
8+ from traitlets .config import LoggingConfigurable
209
21- # Check if all pids are alive
22- for proc in procs :
23- exists = check_pid (proc .proc .pid )
24- if not exists :
25- await manager .del_server_proxy_app (proc .name )
10+ from jupyter_server .utils import url_path_join as ujoin
2611
2712
28- class ServerProxyAppManager :
13+ ServerProxy = namedtuple (
14+ "ServerProxy" ,
15+ [
16+ "name" ,
17+ "url" ,
18+ "cmd" ,
19+ "port" ,
20+ "managed" ,
21+ "unix_socket"
22+ ],
23+ defaults = ["" ] * 6
24+ )
25+ ServerProxyProc = namedtuple (
26+ "ServerProxyProc" ,
27+ [
28+ "name" ,
29+ "proc"
30+ ],
31+ defaults = ["" ] * 2
32+ )
33+
34+
35+ class ServerProxyAppManager (LoggingConfigurable ):
2936 """
3037 A class for listing and stopping server proxies that are started
3138 by jupyter server proxy.
3239 """
3340
34- def __init__ (self ):
35- """Initialize the server proxy manager"""
36- # List of server proxy apps
37- self .server_proxy_apps = []
41+ server_proxy_apps = List (
42+ help = "List of server proxy apps"
43+ )
3844
39- # List of server proxy app proc objects. For internal use only
40- self ._server_proxy_procs = []
45+ _server_proxy_procs = List (
46+ help = "List of server proxy app proc objects"
47+ )
4148
42- # Total number of currently running proxy apps
43- self .num_active_server_proxy_apps = 0
49+ num_active_server_proxy_apps = Int (
50+ 0 ,
51+ help = "Total number of currently running proxy apps"
52+ )
4453
45- async def add_server_proxy_app (self , name , base_url , cmd , port , proc ):
54+ def add_server_proxy_app (self , name , base_url , cmd , port , proc , unix_socket ):
4655 """Add a launched proxy server to list"""
4756 self .num_active_server_proxy_apps += 1
4857
@@ -54,6 +63,7 @@ async def add_server_proxy_app(self, name, base_url, cmd, port, proc):
5463 cmd = " " .join (cmd ),
5564 port = port ,
5665 managed = True if proc else False ,
66+ unix_socket = unix_socket if unix_socket is not None else ''
5767 )
5868 )
5969
@@ -65,24 +75,25 @@ async def add_server_proxy_app(self, name, base_url, cmd, port, proc):
6575 proc = proc ,
6676 )
6777 )
78+ self .log .debug ("Server proxy %s added to server proxy manager" % name )
6879
69- async def del_server_proxy_app (self , name ):
80+ def del_server_proxy_app (self , name ):
7081 """Remove a launched proxy server from list"""
7182 self .server_proxy_apps = [
7283 app for app in self .server_proxy_apps if app .name != name
7384 ]
7485 self ._server_proxy_procs = [
7586 app for app in self ._server_proxy_procs if app .name != name
7687 ]
77- self .num_active_server_proxy_apps -= 1
88+ self .num_active_server_proxy_apps = len ( self . server_proxy_apps )
7889
7990 def get_server_proxy_app (self , name ):
8091 """Get a given server proxy app"""
81- return next ((app for app in self .server_proxy_apps if app .name == name ), {} )
92+ return next ((app for app in self .server_proxy_apps if app .name == name ), ServerProxy () )
8293
8394 def _get_server_proxy_proc (self , name ):
8495 """Get a given server proxy app"""
85- return next ((app for app in self ._server_proxy_procs if app .name == name ), {} )
96+ return next ((app for app in self ._server_proxy_procs if app .name == name ), ServerProxyProc () )
8697
8798 def list_server_proxy_apps (self ):
8899 """List all active server proxy apps"""
@@ -107,21 +118,32 @@ async def terminate_server_proxy_app(self, name):
107118 await app .proc .terminate ()
108119
109120 # Remove proxy app from list
110- await self .del_server_proxy_app (name )
121+ self .del_server_proxy_app (name )
122+
123+ self .log .debug ("Server proxy %s removed from server proxy manager" % name )
111124
112125 return True
113126 except (KeyError , AttributeError ):
127+ self .log .warning ("Server proxy %s not found in server proxy manager" % name )
114128 return None
115129
116130 async def terminate_all (self ):
117131 """Close all server proxy and cleanup"""
118132 for app in self .server_proxy_apps :
119133 await self .terminate_server_proxy_app (app )
120134
121-
122- # Create a default manager to keep track of server proxy apps.
123- manager = ServerProxyAppManager ()
124-
125- # Create a Periodic call back function to check the status of processes
126- pc = PeriodicCallback (monitor_server_proxy_procs , 1e4 )
127- pc .start ()
135+ async def monitor (self , monitor_interval ):
136+ while True :
137+ procs = self ._list_server_proxy_procs ()
138+
139+ # Check if processes are running
140+ for proc in procs :
141+ running = proc .proc .running
142+ if not running :
143+ self .log .warning (
144+ "Server proxy %s is not running anymore. "
145+ "Removing from server proxy manager" % proc .name
146+ )
147+ self .del_server_proxy_app (proc .name )
148+
149+ await asyncio .sleep (monitor_interval )
0 commit comments