@@ -513,6 +513,69 @@ def start_node(node_num):
513
513
return processes
514
514
515
515
516
+ def start_code_watchdog (num_nodes , start_index ):
517
+ # This is a workaround to avoid importing watchdog if it's not installed.
518
+ # Otherwise, we will need to install watchdog on all test machines, where
519
+ # it will never be actually used.
520
+ from watchdog .observers import Observer
521
+ from watchdog .events import FileSystemEventHandler
522
+
523
+ class BeamFileHandler (FileSystemEventHandler ):
524
+ def __init__ (self , num_nodes , start_index ):
525
+ self .num_nodes = num_nodes
526
+ self .start_index = start_index
527
+
528
+ def on_modified (self , event ):
529
+ self .handle_file_change (event .src_path )
530
+
531
+ def on_created (self , event ):
532
+ self .handle_file_change (event .src_path )
533
+
534
+ def on_moved (self , event ):
535
+ self .handle_file_change (event .dest_path )
536
+
537
+ def handle_file_change (self , file_path ):
538
+ if file_path .endswith ('.beam' ):
539
+ module_name = os .path .splitext (os .path .basename (file_path ))[0 ]
540
+ self .reload_module (module_name )
541
+
542
+ def reload_module (self , module_name ):
543
+ for i in range (self .num_nodes ):
544
+ port = base_api_port + self .start_index + i
545
+ node = f"http://127.0.0.1:{ port } "
546
+ url = f"{ node } /diag/eval"
547
+
548
+ # Erlang code to reload the module
549
+ erlang_code = f"{{module, _}} = c:l({ module_name } )."
550
+
551
+ try :
552
+ response = requests .post (url ,
553
+ auth = (default_username , default_pass ),
554
+ data = erlang_code )
555
+ if response .status_code == 200 :
556
+ print (f"*** reloaded { module_name } on { node } " )
557
+ else :
558
+ print (f"*** reload failed for { module_name } on { node } :" \
559
+ f" { response .text } " )
560
+ except Exception as e :
561
+ print (f"*** reload failed for { module_name } on { node } : { e } " )
562
+
563
+ code_path = os .path .join (ns_server_dir , '_build' , 'default' , 'lib' )
564
+ print (f"*** Starting code watchdog for { code_path } " )
565
+ # Create a watchdog observer
566
+ observer = Observer ()
567
+ handler = BeamFileHandler (num_nodes , start_index )
568
+ observer .schedule (handler , code_path , recursive = True )
569
+ observer .start ()
570
+ return observer
571
+
572
+
573
+ def stop_code_watchdog (observer ):
574
+ observer .stop ()
575
+ observer .join ()
576
+ print ("*** Code watchdog stopped" )
577
+
578
+
516
579
def wait_nodes_up (num_nodes = 1 , start_index = 0 , master_passwords = None ,
517
580
root_dir = None , timeout_s = node_start_timeout_s ,
518
581
node_urls = None , verbose = True ):
0 commit comments