I have telegram bot. I use express. I connect to bot via webwook. But the server shutting down after a min. I have start tier. Why this happens?
==> Your service is live
Jan 17 11:41:49 AM[2025-01-17T08:41:49.756Z] GET /
Jan 17 11:41:49 AM[2025-01-17T08:41:49.756Z] GET /
Jan 17 11:41:49 AMRoot route accessed
Jan 17 11:41:49 AM[2025-01-17T08:41:49.758Z] GET / 200 2ms
Jan 17 11:42:49 AMReceived SIGTERM. Shutting down gracefully…
Jan 17 11:42:49 AMRemoving webhook…
Jan 17 11:42:49 AMCleaning up botpress service…
Jan 17 11:42:49 AMBotpressService cleanup completed
Jan 17 11:42:49 AMClosing HTTP server…
Jan 17 11:42:49 AMCleanup completed successfully
Jan 17 11:42:49 AMProcess exiting with code: 0
app.get("/", (_req, res) => {
console.log("Root route accessed");
return res.status(200).json({
status: "ok",
timestamp: new Date().toISOString(),
service: "telegram-bot",
uptime: process.uptime(),
});
});
app.get("/health", async (_req, res) => {
try {
const health: HealthCheckResponse = {
status: "ok",
timestamp: new Date().toISOString(),
uptime: process.uptime(),
memory: process.memoryUsage(),
};
res.status(200).json(health);
} catch (error) {
console.error("Health check error:", error);
res.status(500).json({ error: "Health check failed" });
}
});
// Keep-alive ping endpoint
app.get("/ping", (_req, res) => {
res.status(200).send("pong");
});
// Disable GET for payment callback
app.get("/payment/callback", (_req, res) => {
res.status(405).json({ error: "Method not allowed" });
});
app.use((err: Error, _req: express.Request, res: express.Response, next: express.NextFunction) => {
console.error("Unhandled error:", err);
res.status(500).json({ error: "Internal server error" });
next(err);
});
const startServer = async (): Promise<void> => {
let server: Server | undefined;
let isShuttingDown = false;
try {
// Start the server
server = app.listen(config.port, () => {
console.log(`Server is running on port ${config.port}`);
});
// Set up webhook
console.log("Setting up webhook...");
const webhookUrl = `${config.webhookUrl}/webhook/${config.telegramToken}`;
try {
await bot.telegram.setWebhook(webhookUrl, {
drop_pending_updates: true,
allowed_updates: ["message", "callback_query"],
max_connections: 100,
});
console.log("Successfully set webhook to:", webhookUrl);
// Verify webhook
const webhookInfo = await bot.telegram.getWebhookInfo();
console.log("Webhook info:", webhookInfo);
if (webhookInfo.url !== webhookUrl) {
throw new Error(`Webhook URL mismatch. Expected: ${webhookUrl}, Got: ${webhookInfo.url}`);
}
console.log("Verifying bot permissions...");
try {
const me = await bot.telegram.getMe();
console.log("Bot info:", {
id: me.id,
username: me.username,
canJoinGroups: me.can_join_groups,
canReadMessages: me.can_read_all_group_messages,
supportsInline: me.supports_inline_queries,
});
} catch (error) {
console.error("Failed to verify bot permissions:", error);
throw error;
}
} catch (error) {
console.error("Webhook setup error:", error);
throw error;
}
// Graceful shutdown handler
const cleanup = async (signal: string): Promise<void> => {
if (isShuttingDown) return;
isShuttingDown = true;
console.log(`Received ${signal}. Shutting down gracefully...`);
try {
// Set a timeout for graceful shutdown
const shutdownTimeout = setTimeout(() => {
console.error("Forced shutdown due to timeout");
process.exit(1);
}, 10000);
// Cleanup tasks
console.log("Removing webhook...");
await bot.telegram.deleteWebhook();
console.log("Cleaning up botpress service...");
await botpressService.cleanup();
if (server) {
console.log("Closing HTTP server...");
await new Promise<void>((resolve) => server!.close(() => resolve()));
}
clearTimeout(shutdownTimeout);
console.log("Cleanup completed successfully");
process.exit(0);
} catch (error) {
console.error("Error during cleanup:", error);
process.exit(1);
}
};
// Signal handlers
["SIGINT", "SIGTERM", "SIGUSR2"].forEach((signal) => {
process.once(signal, () => cleanup(signal));
});
// Handle unhandled rejections
process.on("unhandledRejection", (error: unknown) => {
console.error("Unhandled Rejection:", error);
});
// Keep the process alive
process.on("exit", (code) => {
console.log(`Process exiting with code: ${code}`);
});
} catch (error) {
console.error("Failed to start server:", error);
if (server) {
server.close();
}
process.exit(1);
}
};
startServer().catch((error: Error) => {
console.error("Failed to start application:", error.message);
process.exit(1);
});