2121
2222TARGET_MEMORY_TRIGGER_PERCENT = 70
2323TARGET_CLEAR_TMP_ARR_SECONDS = 180
24+ TARGET_INFLATE_DELAY_SECONDS = 90
2425
2526
2627if LOG_DIR .is_dir ():
3132_tmp_array_triggered = False
3233_tmp_arr = None
3334_tmp_arr_timer = None
35+ _inflate_delay_timer = None
3436
3537
3638def _clear_tmp_arr ():
@@ -41,10 +43,31 @@ def _clear_tmp_arr():
4143 print (f"tmp_arr cleared after { TARGET_CLEAR_TMP_ARR_SECONDS } s" )
4244
4345
46+ def _inflate_memory ():
47+ global _tmp_arr , _tmp_arr_timer , _inflate_delay_timer
48+ _inflate_delay_timer = None
49+ total_memory = get_container_total_memory ()
50+ used_memory = get_container_used_memory ()
51+ target_memory = total_memory * TARGET_MEMORY_TRIGGER_PERCENT / 100
52+ array_size = int (
53+ (target_memory - used_memory ) / 8
54+ ) # assuming float64 (8 bytes)
55+ if array_size > 0 :
56+ print (
57+ f"Inflating memory with array of size { array_size } to trigger ECS scaling"
58+ )
59+ _tmp_arr = np .ones (array_size , dtype = np .float64 )
60+ _tmp_arr_timer = threading .Timer (
61+ TARGET_CLEAR_TMP_ARR_SECONDS , _clear_tmp_arr
62+ )
63+ _tmp_arr_timer .daemon = True
64+ _tmp_arr_timer .start ()
65+
66+
4467# 2. Health Check & Index Redirect
4568class HealthHandler (RequestHandler ):
4669 def get (self ):
47- global _tmp_arr , _tmp_arr_timer , _tmp_array_triggered
70+ global _tmp_arr , _tmp_arr_timer , _tmp_array_triggered , _inflate_delay_timer
4871 total_memory = get_container_total_memory ()
4972 used_memory = get_container_used_memory ()
5073 mem_percent = used_memory / total_memory * 100
@@ -61,36 +84,34 @@ def get(self):
6184 )
6285 elif len (gui_sessions ) >= max_gui_sessions :
6386 self .set_status (200 )
87+ # inflate RAM once per threshold-exceeded event so ECS spawns a new task;
88+ # wait TARGET_INFLATE_DELAY_SECONDS first so existing sessions finish loading
89+ if _tmp_arr is None and _inflate_delay_timer is None and not _tmp_array_triggered :
90+ _tmp_array_triggered = True
91+ print (
92+ f"Max sessions reached, will inflate memory in { TARGET_INFLATE_DELAY_SECONDS } s"
93+ )
94+ _inflate_delay_timer = threading .Timer (
95+ TARGET_INFLATE_DELAY_SECONDS , _inflate_memory
96+ )
97+ _inflate_delay_timer .daemon = True
98+ _inflate_delay_timer .start ()
6499 busy_msg = "(MAX SESSIONS REACHED)"
65100 if _tmp_arr is not None :
66101 busy_msg += " (inflating memory)"
102+ elif _inflate_delay_timer is not None :
103+ busy_msg += " (waiting to inflate memory)"
67104 elif _tmp_array_triggered :
68105 busy_msg += " (inflated memory released)"
69106 self .write (
70107 f"Busy { busy_msg } :\n Memory at { mem_percent :.1f} % - Num sessions: { len (gui_sessions )} "
71108 f"(max { max_gui_sessions } ) Task ID: { task_id } "
72109 )
73- # inflate RAM once per threshold-exceeded event so ECS spawns a new task
74- if _tmp_arr is None and not _tmp_array_triggered :
75- _tmp_array_triggered = True
76- total_memory = get_container_total_memory ()
77- used_memory = get_container_used_memory ()
78- target_memory = total_memory * TARGET_MEMORY_TRIGGER_PERCENT / 100
79- array_size = int (
80- (target_memory - used_memory ) / 8
81- ) # assuming float64 (8 bytes)
82- if array_size > 0 :
83- print (
84- f"Inflating memory with array of size { array_size } to trigger ECS scaling"
85- )
86- _tmp_arr = np .ones (array_size , dtype = np .float64 )
87- _tmp_arr_timer = threading .Timer (
88- TARGET_CLEAR_TMP_ARR_SECONDS , _clear_tmp_arr
89- )
90- _tmp_arr_timer .daemon = True
91- _tmp_arr_timer .start ()
92110 else :
93111 _tmp_array_triggered = False
112+ if _inflate_delay_timer is not None :
113+ _inflate_delay_timer .cancel ()
114+ _inflate_delay_timer = None
94115 self .set_status (200 )
95116 self .write (
96117 f"Healthy:\n Memory at { mem_percent :.1f} % - Num sessions: { len (gui_sessions )} "
0 commit comments