11import os
22import shutil
3+ import threading
34from argparse import ArgumentParser
45
56import requests
7+ import numpy as np
68import psutil
79import panel as pn
810from tornado .web import RequestHandler
1214from aind_ephys_portal .panel .logging import list_gui_sessions , get_max_number_of_gui_sessions , LOG_DIR # noqa: F401
1315
1416
17+ TARGET_MEMORY_TRIGGER_PERCENT = 75
18+ TARGET_CLEAR_TMP_ARR_SECONDS = 30
19+
20+
1521if LOG_DIR .is_dir ():
1622 print (f"Cleaning up old log files in { LOG_DIR } ..." )
1723 shutil .rmtree (LOG_DIR )
@@ -31,20 +37,57 @@ def get_ecs_task_id():
3137MAX_GUI_SESSIONS_PER_TASK = get_max_number_of_gui_sessions ()
3238print (f"Max GUI sessions per task: { MAX_GUI_SESSIONS_PER_TASK } " )
3339
40+ _tmp_array_triggered = False
41+ _tmp_arr = None
42+ _tmp_arr_timer = None
43+
44+
45+ def _clear_tmp_arr ():
46+ global _tmp_arr , _tmp_arr_timer
47+ print ("Clearing temporary array to free up memory..." )
48+ _tmp_arr = None
49+ _tmp_arr_timer = None
50+ print (f"tmp_arr cleared after { TARGET_CLEAR_TMP_ARR_SECONDS } s" )
51+
3452# 2. Health Check & Index Redirect
3553class HealthHandler (RequestHandler ):
3654 def get (self ):
55+ global _tmp_arr , _tmp_arr_timer , _tmp_array_triggered
3756 mem = psutil .virtual_memory ()
3857 # count number of GUI app sessions
3958 gui_sessions = list_gui_sessions ()
4059 task_id = get_ecs_task_id ()
41- if mem .percent > 70 or len (gui_sessions ) > MAX_GUI_SESSIONS_PER_TASK :
42- self .set_status (503 )
60+ if mem .percent > TARGET_MEMORY_TRIGGER_PERCENT :
61+ self .set_status (200 )
62+ self .write (
63+ f"Busy (RAM Usage):\n Memory at { mem .percent } % - Num sessions: { len (gui_sessions )} "
64+ f"(max { MAX_GUI_SESSIONS_PER_TASK } ) Task ID: { task_id } "
65+ )
66+ elif len (gui_sessions ) > MAX_GUI_SESSIONS_PER_TASK :
67+ self .set_status (200 )
68+ busy_msg = "(MAX SESSIONS EXCEEDED)"
69+ if _tmp_arr is not None :
70+ busy_msg += " (inflating memory)"
71+ elif _tmp_array_triggered :
72+ busy_msg += " (inflated memory released)"
4373 self .write (
44- f"Busy:\n Memory at { mem .percent } % - Num sessions: { len (gui_sessions )} "
74+ f"Busy { busy_msg } :\n Memory at { mem .percent } % - Num sessions: { len (gui_sessions )} "
4575 f"(max { MAX_GUI_SESSIONS_PER_TASK } ) Task ID: { task_id } "
4676 )
77+ # inflate RAM once per threshold-exceeded event so ECS spawns a new task
78+ if _tmp_arr is None and not _tmp_array_triggered :
79+ _tmp_array_triggered = True
80+ total_memory = psutil .virtual_memory ().total
81+ used_memory = psutil .virtual_memory ().used
82+ target_memory = total_memory * TARGET_MEMORY_TRIGGER_PERCENT / 100
83+ array_size = int ((target_memory - used_memory ) / 8 ) # assuming float64 (8 bytes)
84+ _tmp_arr = np .ones (array_size , dtype = np .float64 )
85+ print (f"Inflated memory with array of size { array_size } to trigger ECS scaling" )
86+ _tmp_arr_timer = threading .Timer (TARGET_CLEAR_TMP_ARR_SECONDS , _clear_tmp_arr )
87+ _tmp_arr_timer .daemon = True
88+ _tmp_arr_timer .start ()
4789 else :
90+ _tmp_array_triggered = False
4891 self .set_status (200 )
4992 self .write (
5093 f"Healthy:\n Memory at { mem .percent } % - Num sessions: { len (gui_sessions )} "
0 commit comments