Skip to content

Commit 1a5e982

Browse files
committed
fix: use synchronous FastAPI webhook to prevent Cloud Run from freezing the bot during CPU throttling
1 parent 5701264 commit 1a5e982

1 file changed

Lines changed: 44 additions & 13 deletions

File tree

main.py

Lines changed: 44 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@
55
import traceback
66
from telegram.constants import ParseMode
77
from telegram.ext import Application, CommandHandler, CallbackQueryHandler, MessageHandler, filters
8+
from contextlib import asynccontextmanager
9+
from fastapi import FastAPI, Request, Response
10+
import uvicorn
811

912
from bot_logic import COMMANDS, button
10-
from models import init_db
1113
from tg_ids import ROZEN_CHATID
1214

1315
async def error_handler(update, context):
@@ -54,16 +56,51 @@ async def post_init(application: Application):
5456
except Exception as e:
5557
logging.getLogger("DCUBABOT").error(f"Failed to set bot commands: {e}")
5658

59+
# Instancia global de la aplicación de Telegram
60+
application = Application.builder().token(os.environ["TELEGRAM_BOT_TOKEN"]).post_init(post_init).build()
61+
62+
@asynccontextmanager
63+
async def lifespan(app: FastAPI):
64+
# Setup de la aplicación de Telegram al arrancar FastAPI
65+
await application.initialize()
66+
await application.start()
67+
68+
webhook_url = os.environ["WEBHOOK_URL"]
69+
token = os.environ["TELEGRAM_BOT_TOKEN"]
70+
url = f'{webhook_url.rstrip("/")}/{token}'
71+
await application.bot.set_webhook(url=url)
72+
73+
yield
74+
75+
# Shutdown
76+
await application.stop()
77+
await application.shutdown()
78+
79+
app = FastAPI(lifespan=lifespan)
80+
81+
@app.post("/{token}")
82+
async def telegram_webhook(token: str, request: Request):
83+
if token != os.environ["TELEGRAM_BOT_TOKEN"]:
84+
return Response(status_code=403)
85+
86+
try:
87+
data = await request.json()
88+
update = telegram.Update.de_json(data=data, bot=application.bot)
89+
# Await the processing SYNCHRONOUSLY before returning 200 OK
90+
# This prevents Cloud Run from throttling the CPU while the bot is doing work
91+
await application.process_update(update)
92+
except Exception as e:
93+
logging.error(f"Failed to process update: {e}")
94+
95+
return Response(status_code=200)
96+
5797
def main():
5898
"""Start the bot."""
5999
logging.basicConfig(
60100
level=logging.INFO,
61101
format='[%(asctime)s] - [%(name)s] - [%(levelname)s] - %(message)s',
62102
)
63103

64-
65-
application = Application.builder().token(os.environ["TELEGRAM_BOT_TOKEN"]).post_init(post_init).build()
66-
67104
application.add_error_handler(error_handler)
68105

69106
# Add the logging middleware handler with a high priority
@@ -74,15 +111,9 @@ def main():
74111

75112
application.add_handler(CallbackQueryHandler(button))
76113

77-
webhook_url = os.environ["WEBHOOK_URL"]
78-
79-
# Start the Bot
80-
application.run_webhook(
81-
listen="0.0.0.0",
82-
port=int(os.environ.get("PORT", 8080)),
83-
url_path=os.environ["TELEGRAM_BOT_TOKEN"],
84-
webhook_url=f'{webhook_url.rstrip("/")}/{os.environ["TELEGRAM_BOT_TOKEN"]}',
85-
)
114+
# Run the FastAPI app via uvicorn
115+
port = int(os.environ.get("PORT", 8080))
116+
uvicorn.run(app, host="0.0.0.0", port=port)
86117

87118
if __name__ == "__main__":
88119
main()

0 commit comments

Comments
 (0)