@@ -378,7 +378,7 @@ def __repr__(self):
378
378
fields ["profile_dir" ] = repr (profile_dir )
379
379
380
380
if self .controller :
381
- fields ["controller" ] = "<running >"
381
+ fields ["controller" ] = f"< { self . controller . state } >"
382
382
if self .engines :
383
383
fields ["engine_sets" ] = list (self .engines )
384
384
@@ -398,7 +398,7 @@ def _cls_str(cls):
398
398
399
399
cluster_info ["class" ] = _cls_str (self .__class__ )
400
400
401
- if self .controller :
401
+ if self .controller and self . controller . state != 'after' :
402
402
d ["controller" ] = {
403
403
"class" : _cls_str (self .controller_launcher_class ),
404
404
"state" : None ,
@@ -411,7 +411,8 @@ def _cls_str(cls):
411
411
}
412
412
sets = d ["engines" ]["sets" ]
413
413
for engine_set_id , engine_launcher in self .engines .items ():
414
- sets [engine_set_id ] = engine_launcher .to_dict ()
414
+ if engine_launcher .state != 'after' :
415
+ sets [engine_set_id ] = engine_launcher .to_dict ()
415
416
return d
416
417
417
418
@classmethod
@@ -447,13 +448,15 @@ def from_dict(cls, d, **kwargs):
447
448
)
448
449
except launcher .NotRunning as e :
449
450
self .log .error (f"Controller for { cluster_key } not running: { e } " )
451
+ else :
452
+ self .controller .on_stop (self ._controller_stopped )
450
453
451
454
engine_info = d .get ("engines" )
452
455
if engine_info :
453
456
cls = self .engine_launcher_class = import_item (engine_info ["class" ])
454
457
for engine_set_id , engine_state in engine_info .get ("sets" , {}).items ():
455
458
try :
456
- self .engines [engine_set_id ] = cls .from_dict (
459
+ self .engines [engine_set_id ] = engine_set = cls .from_dict (
457
460
engine_state ,
458
461
engine_set_id = engine_set_id ,
459
462
parent = self ,
@@ -462,6 +465,9 @@ def from_dict(cls, d, **kwargs):
462
465
self .log .error (
463
466
f"Engine set { cluster_key } { engine_set_id } not running: { e } "
464
467
)
468
+ else :
469
+ engine_set .on_stop (partial (self ._engines_stopped , engine_set_id ))
470
+
465
471
# check if state changed
466
472
if self .to_dict () != d :
467
473
# if so, update our cluster file
@@ -527,7 +533,9 @@ def update_cluster_file(self):
527
533
# setting cluster_file='' disables saving to disk
528
534
return
529
535
530
- if not self .controller and not self .engines :
536
+ if (not self .controller or self .controller .state == 'after' ) and not any (
537
+ es .state == 'after' for es in self .engines .values ()
538
+ ):
531
539
self .remove_cluster_file ()
532
540
else :
533
541
self .write_cluster_file ()
@@ -594,6 +602,7 @@ def add_args(args):
594
602
def _controller_stopped (self , stop_data = None ):
595
603
"""Callback when a controller stops"""
596
604
self .log .info (f"Controller stopped: { stop_data } " )
605
+ self .update_cluster_file ()
597
606
598
607
async def start_engines (self , n = None , engine_set_id = None , ** kwargs ):
599
608
"""Start an engine set
@@ -839,6 +848,17 @@ def load_clusters(
839
848
- single profile by name
840
849
- all IPython profiles, if nothing else specified
841
850
"""
851
+
852
+ # first, check our current clusters
853
+ for key , cluster in list (self .clusters .items ()):
854
+ # remove stopped clusters
855
+ # but not *new* clusters that haven't started yet
856
+ if (cluster .controller and cluster .controller .state == 'after' ) and all (
857
+ es .state == 'after' for es in cluster .engines .values ()
858
+ ):
859
+ self .log .info ("Removing stopped cluster {key}" )
860
+ self .clusters .pop (key )
861
+
842
862
if profile_dirs is None :
843
863
if profile_dir is not None :
844
864
profile_dirs = [profile_dir ]
0 commit comments