From 98eeb46c61c98159cf4eb8b4a75cb56a5811d928 Mon Sep 17 00:00:00 2001 From: pacnpal <183241239+pacnpal@users.noreply.github.com> Date: Mon, 24 Feb 2025 16:54:22 -0500 Subject: [PATCH] Refactor web server initialization for graceful shutdown; update .gitignore to exclude additional cache files --- .gitignore | 4 ++++ discord_glhf/__pycache__/api.cpython-313.pyc | Bin 16439 -> 16849 bytes discord_glhf/__pycache__/bot.cpython-313.pyc | Bin 26121 -> 25035 bytes discord_glhf/bot.py | 13 +++++++++---- .../__pycache__/event_handler.cpython-313.pyc | Bin 31432 -> 32225 bytes .../web/__pycache__/app.cpython-313.pyc | Bin 4571 -> 5752 bytes discord_glhf/web/app.py | 13 ++++++++----- 7 files changed, 21 insertions(+), 9 deletions(-) diff --git a/.gitignore b/.gitignore index 880743f..df2410f 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,7 @@ queue_state.json system_prompt.yaml discord_glhf/__pycache__/bot.cpython-313.pyc discord_glhf/handlers/__pycache__/event_handler.cpython-313.pyc +discord_glhf/__pycache__/api.cpython-313.pyc +discord_glhf/__pycache__/bot.cpython-313.pyc +discord_glhf/handlers/__pycache__/event_handler.cpython-313.pyc +discord_glhf/web/__pycache__/app.cpython-313.pyc diff --git a/discord_glhf/__pycache__/api.cpython-313.pyc b/discord_glhf/__pycache__/api.cpython-313.pyc index 9a389a5b23115e95d9e9cfc310e6c6b8cf191b55..85387f55acdf41abb7d0fd20507c294e9a6a7d70 100644 GIT binary patch delta 2640 zcmb_eZA@F&89vAMH3n?J@wa`keQmHYreI@Sz`;8%mS07fopp0q*|wr zru(sKnzUx8)#$V>sg$+pezeP&R<>2!RB6$+Zkj2S5982D`@3p1rD9n%ZRcESTGnX4 zb}c{mz3=R~}8#pZ+td;Y6G;C&ckK%acr}4uK4W~z6 zH!}tUC((euX#jZRc!0Df7iUCji>|ma2oImf8_@e^Mr~vpNe#^RW4?(q5tgYb&tjWH zV*t!Z02ngk8U_@n^$NCGloLXemJVqPcHXd_9Bm;!*oOXY(do=3 zfNc**cuR!hh}}VKGKjR3v!FJ*67#N^G-?Zn#~5!v6bV4I6W!73(D!JCt*aTb-OVxx z`XSqMQ3}9S_@XpSDFIJ&bhMlFQuPwK@d%bmM|;sBr<)IV)Mk#lC#Ws>8nE zG>l^joR#ep7qFioZ(|2ITMM@0`#6T5M6aDa!`Ve|6ZYyHI4fU`XE-KbG48?VVsO0g z(*__qkhcIpztk4{nS54*B!$QL-(yt(&Q6ru8rh-z@VtX_9CfS4S{%_KGBz5rs!W5N z=#GeIYsvN5B>oU;T3B%jr`;oak%UCxKBjVyn} z6hH~crXMnA;rQA7Di?rw1KvZi_G8iiN9|eACbfZCh^Kgk0X2XeKJ>s|sp~oPlYMdO&t}T^ZIsSJ&&cuzOoePjD8!vSk}P#D z5*cK(nuWNKN=&7b$+;;Zky=RdsYJFootR%p2=Vk4A#uth7ZNx{z-JZ+mkC_Jkd>#> zLLxq&rATUOxy@Av>$62-o$2`8TQ|+T z11%`*gL?{exwc%nr89r1Dkv*@PPSi$uGhXU>4vDY?f}xL$!CS{qER2SxO93?4(v6z zpIoy&y6x-v&Cr@JdQ-LQ^lf?TeyV-b{1fxa(3*cB;~h9?p^PO50KoB z<;y?ztVGvbolB>8ZLZsmZ?wJE_D08R9b0bi?a`Z0ADo28()I@+D0ki%{O(}J!>!Yc zBRSe3K6%?#E^fAmSKGsxwn)ZvcAXwR3bn3`{d(%>Q<>JGj3>NKN4A``2g65o_lTVR zFF~L-d`J0hWv0Aky{vW1;5e8*PI>UrB^j^|!w2`zN`Uzc{CG@4nT#d(U7#}bu^ZR; z$9@z7BfV+xt{S}Pn!o(S=uri6=1=y=(9?dVZt}m}dt*?dcK`F>u_M2@PNJ|+_Gi(b z{L#hV;h(x^Pci2`@UBxCE0*64$O$(0`mpOAk2$86{joq!P}M_Nf3CM+%&40%t`>Dm zClz2#1!H>oT8U_@yGkc&rR(-$99Z|lm`S!?BO|sC;*9lrO{`M#9tC5x{5^S>Iks3S z*{~~de4_@&Z1Rmq2zSFzxEu9;%-wX7=w=;^G4f3xiEcKK=w`5s#^LP~q|tUcj5%f7 zRubNJknpzCfMsllNHj~qi5gi}PNLZ&C5~qGkk}?TxrlEx#D%gp(Zz`96tPk};i0n4 zrtvCj=Y$NG+tHJ9I}9AJknK1qV!KJRohlV(?gUK}6;!T-Fms};TsfSu%W_u2%sB}& zS3zNB&Lbt98r&rea<%eFsvy?@CmNNxpc32nAX&+KGLmqQ5^cpJ=Uvi!K?(6R7GirB z(B~QHE=^(2E<+KIOM2e3d^hke1$p#R^L*JN{wxYt2|P*QM@S#?z+0#@q=R2ZBcU|> z0eUCY3m;!DYx$SNEVA+c0wBl3&687znrtkZ&O2Dw^r2gWp0gbhMk_CXPk|P7GN^>wI$N%3Pvd_$~TdM@Su!!vT07 Ih&Pe;ACx_E-v9sr delta 2212 zcmb_deQXnD7=PdEUDs`0_tD<^-Ro_vU024~y0VXUtlbyefQ{X8!BS^vup35O@HR}8 zn2AOMMicdoaU>W~iGY7FmziLM5HJz{z{E|O(Y0Vq{M%%(nTf=Y_r1~Kz(2jFzkBX^ ze(&@Ap6A}Xn|lpjcm?W~ii!#VK2GpQM)TUIbyhufSvTX=(|Hw=M%=*QkVIjtUa>SH zPtIb4=-b334d`tv&o<&{)r06NUoRQZ2@7vzB}xx^_XChDkJgeRMRNhZNhd@z8Zjb%+bAO?L@(mcpW#BL)t=|#0wGNVCT6%wp$ ziGPHHKA-~N1^B*dfYE}aMY0G%QmCkd$c+tR zsTN@?irMr?V>hs!(NHd*AGbn|q!oS4@||50#6r3yE5;HZlauZQ4j_ifFURkr*4K1` zQJaHQ=|n^27DFGVuajhxY-ExxJ-L+Ct93!_8!XNy_9*k)Mlfj?dnJ1STd^;33||p1 zSL;fzjSv_J8M&4E`Uv zM?jm310xW3cA5tp0oe-ZUA~G9uljMf{kiJG4s@LlxQEELTHn*CZJkC}uKy-M*@DH2 zQu^^JJnS*2qe(RaJ>tyk6&vV{nZogS;!s?UjUSfdJsw7mVB$HwJ& zEHU%9s}8a<*=W08GIu8qjlbyJe=s>7PmZH~)#srb6?@)9mpom%1X)^2Ac+C7HGb$s z+iNbt1S<2!@>{Vp1LI>(^p3X@UGVy0Wad}z85Olyj!xFu^Y0X@OA3zB%R2OJ-FeuI z4sTw8WhhbafOF`rdVb=jD=_B@eARbFzTxVh-1ZaaI@>hWcCKxz{akz6?LE8a)XOVA z#-v*T814{Q-U4{{8SN+9+1lQev+tJErCij7uTVMMFG!6>#STpX=XrHq9*kg9-@Vmehx6Wa~(ij+qmF;l4^jFhQU zZDCtv!c5JZwKzUs1tY9_-bJ|cHH16w#c?y0){s*OKPyP68184IWsyms=R-yVxm?r$i(_*CDc|IQ6OP6F1UeZq zsg=M}=<84&dx4}NrDZn(@*K-D`YTiikE2cDt?(jBgiY`=dL!Ig8dk%8co!%qxd}7> E0iTKV)&Kwi diff --git a/discord_glhf/__pycache__/bot.cpython-313.pyc b/discord_glhf/__pycache__/bot.cpython-313.pyc index da38c59727eafa158e182fe9a5641fae7b1cc3c4..839b8753f97d96dd4a6a9b6f6bc2bf587cce3fb0 100644 GIT binary patch delta 4505 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

)E}PAbSPU>d77r~ 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 fzkkT^87lq^nV!mqrMT)bqVS6ua>;L%(z*W!8o None: """Initialize API and queue services.""" @@ -84,7 +84,8 @@ class DiscordBot: logger.info("Initializing web interface...") app = init_app(self.event_handler) web_port = 5000 - asyncio.create_task(run_webserver(start_port=web_port)) + self.web_shutdown = asyncio.Event() + asyncio.create_task(run_webserver(start_port=web_port, shutdown_event=self.web_shutdown)) logger.info("Web interface initialized (first available port in range 5000-5009 will be used)") # Start API manager @@ -255,8 +256,12 @@ class DiscordBot: stop_tasks = [] if self.training_manager and self.training_manager.is_running: stop_tasks.append(self.training_manager.stop()) - # Web app will be stopped when the event loop closes - logger.info("Web app will be stopped with event loop") + # Stop web server gracefully + if self.web_shutdown: + logger.info("Stopping web server...") + self.web_shutdown.set() + await asyncio.sleep(1) # Give web server a moment to shut down + logger.info("Web server stopped") if self.db_pool: stop_tasks.append(self.db_pool.close()) diff --git a/discord_glhf/handlers/__pycache__/event_handler.cpython-313.pyc b/discord_glhf/handlers/__pycache__/event_handler.cpython-313.pyc index 7cab6e0d96b176a61c0c933fb8e59f7470ca90cd..f0bb42f40106820e07ba947cfafd0a83195dc230 100644 GIT binary patch delta 8869 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 delta 7680 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 sEn@f$$$6XDenYD7C!)b+jl>5P9eS2Re^;o&W#< diff --git a/discord_glhf/web/__pycache__/app.cpython-313.pyc b/discord_glhf/web/__pycache__/app.cpython-313.pyc index 7f08b3f60349b7c6aadf27558e1785ea09f207da..e08027ec92894eebbbbae2358b2b487dcee50df3 100644 GIT binary patch delta 2804 zcmahKYfM|$`JDUk13$2_F@%>dMU5kIY5^B%0VJoqUSmeUCF*~sf2yi}J zG3Fo+z%8OR>>P6u7vQ!!MBKo&hbzZC#3P_-rUgxVdokS=AyPH%gS8z#ze$UnEb*R% zVnv4oAyXnhU6l!#Y>~ZIBRb%i+UcrDk4Y`hqSI6pU3IAUkU{GHhqPO)?82hwEF*fK zkggX4VpSb_6_bW(ubB7sT}DWH4pF~Lv9N%L&O;9y!5d2ixKEE3B>KhbUZzAh%_6~R zYvlQ-Wf6j18sH0>a^@@`ONvdgZ8e3T;%l|Pz&gJ`q@21(w{63^C6i61WK#GR$3xVH zbNDuzdc1q&@bJe3Kw1iKF~9zy6EL*_z@zKv%gVs5H*UW1v+mVIvA$z1xnAF~QQ29v zbskVXVgt~|kSdD%0jPA-D+2Msq&p;aQHjS$c21K?4Nx3~_t+2)6h2|^`V9$NT1jg$ zDVHNnzy>$C8eo6G-3ZX6mUiLON>i<&}v6)nnr2*)&73My(OJ6HgD(8s(p5j9Q^C2nfV{g>PLA`6-$zV?-Wb9+N_= zO|+FNBcML8rvuvW1R*r<*2A)drZ)XxS{5`(Sg#t3X3qVd0cQFPGyF`kUZ z!_!K^_-`*A5)0NSZ!AOO2O6PnF5MOazlD5c%4itZH&%k5=Z=<&%TixlBS( zvYL>D>n=!&Ak9nZj5L#xguUiL3Vx!~36S_mZFc^-B6OrM8^Ew~T zWWio~p>!^-B(sFxNS!bFKxFsopIVA>(E7?vaL2QJIzJ}oz?xE}GZ(PGJ z7uw;xUt5qj@Xo70C+~Ot+4IaY_qn&GP`hl|KGM8)Y%Nf%X)OlYmMw2Pwwqd(Et|Ib zeXiPG{a4?SJN+yDYk?1&-f#LSu+=@d-aWYC8(JRPc6x4&-WYvnaqUy1 z%`02|7ysCQu{fLAXHiY(KEgE${wKm-1p^N73s3b|LFDcEM;%=~0#E#n2Z(b89{L(r zrOoDNwtPM7zMfCq56*3cudIi!Y=vjm!!!AZ{<=Hicf&>D`g`J3+Q7<>HY$%l^aSoW-*py)qYq9#XedS}iSZaPPIoc?_W?DH@6D#ZQGvm;)7cc5h$F~1L9=^Yf9dwx9F zWVu((QTzxG?0Zd^;zGqxKY#D!fOY5$f4`dpjr+X}ud<*Bzb>1F7&<894_Q=ZnBOQmehN!n~CJws>%((TDPC9Y+&8I{lq zA`=wQ>Ni@p?n|UqsK7)lm6=U;ma2}>PN3UjF-5v6$6|zD3UaFOo+p&2{lIAEaMO&w zPy4pfiH+(bT~yPOk~LYGC-8zJQb|EG1?8S^d+usBF_)3gkt8snSdqE~V4uYpe}TUD zcht9m`gV|g2f24q?JlZ^|5qG`eT7c%{7^Hl-XFn;b1pA!ut#>ds$H)8bBBAG+*-W3 oxLUV1xl!4^;pn(Nw9Pr*3cnd%ajhmcJV*b;9ox4fuFkOI--q2$RR910 delta 1608 zcmZ8gO-vg{6rSCkwb#2|ga6G2@RIQ7%7ms3LZJxYw3HTQ5Jxdv12X%2BRP*@2dk3uP~6hAE>K?Yg+D#&_A zC~^w`BxZe>=kVX=$kK8Xy0j_oAprnKBP*8u4y-Wu0}6+|1hZl~(UPt?AUPF}b4}qT zFmei^@VWXWZ9(x4Q;K+tR(uzj^~b44VD`*hnmHpK!upf` zG2p?R(TTSc6a3y5+5BR|dcwqRCMcU-LAk1tppg%wsGaDMXM8H7HhkDZ&REs+Dyl5i zG!()T&U(!ZPywqGK1((=xRPF~skv$uUBNI>F^DM>G+ZFuZ+`fj;4`ODz=G^XB!GdI zUACkbw9io-3#6ytvj(JMR+KLd^kIQbX$FZymYqi!nqE+=sIpkCAyT0D(;xUey?ELq zSO9sh$l)+#5CV3scr= zn#~#-TGmhpx$jSDt82~Kh4zT$zATf1_wOiCcnXd>pgkx2Hvh?K(XQh=WQ_f z{11OH?6;@3UrhbMTj&GQpcW;;YrNMJic5jx5cS_(`g8JknpMXMHya8zj>H%8)$ zWrYUEZFe9gMvMoij$Fd}-7hO9WBnXn81+-(Mn8bw^#^sP;}G6H5Pa)s hbM@=hE$Q)0y)9W6hRn$W=>M+w7Z`200hF5l{{w@(MoItx diff --git a/discord_glhf/web/app.py b/discord_glhf/web/app.py index e26c833..3b32a82 100644 --- a/discord_glhf/web/app.py +++ b/discord_glhf/web/app.py @@ -67,7 +67,7 @@ async def send_prompt(): except Exception as e: return jsonify({'error': str(e)}), 500 -async def run_webserver(start_port=5000): +async def run_webserver(start_port=5000, shutdown_event=None): """Run the web server.""" import hypercorn.asyncio from hypercorn.config import Config @@ -87,11 +87,14 @@ async def run_webserver(start_port=5000): logger.info(f"Starting web interface at http://localhost:{port}") try: - await hypercorn.asyncio.serve(app, config) - break - except KeyboardInterrupt: - logger.info("Web server shutdown requested") + await hypercorn.asyncio.serve(app, config, + shutdown_trigger=shutdown_event.wait if shutdown_event else None) break + except Exception as e: + if isinstance(e, KeyboardInterrupt) or (shutdown_event and shutdown_event.is_set()): + logger.info("Web server shutdown requested") + break + raise except OSError: if port == start_port + 9: # Last attempt logger.error(f"Could not find an available port in range {start_port}-{port}")