Did you ever face "stale singleton httpx connection" and "cold-start connection problem" problem, Well I did tonight.

Did you ever face “stale singleton httpx connection” and “cold-start connection problem”? Well, I did tonight.

你是否曾遇到过“陈旧的单例 httpx 连接”和“冷启动连接问题”?我今晚遇到了。

It has been a while since I started learning and building with FastAPI. There is a project where I was thinking about how to add a new feature to an existing one, such as what changes I need to make in the database that need to be reflected in my backend and frontend. I had already launched the web app locally. The problem started when I went back to the web app and reloaded it; it showed this error: ERROR: ConnectTimeout: Unauthorized 401. I was like, “What? Why?” I thought there was some issue with the login endpoint or the refresh token function.

我学习并使用 FastAPI 进行开发已经有一段时间了。最近在一个项目中,我正在思考如何在一个现有功能上添加新特性,比如数据库需要做哪些变更,以及这些变更如何同步到后端和前端。我已经成功在本地运行了该 Web 应用。问题出现在我重新回到网页并刷新时,它报错了:ERROR: ConnectTimeout: Unauthorized 401。我当时很困惑:“什么?为什么?”我以为是登录接口或刷新令牌函数出了问题。

When I did some debugging, I found some new information: “Either Supabase’s edge/pooler (or OS, or an intermediate proxy/NAT) silently kills those idle connections server-side after some timeout, but the client-side pool doesn’t know that.” Since I wasn’t doing anything, the connection became idle, so to save resources, the server-side silently closed that particular connection. When I came back and tried to connect, it gave me this error. The first thought that came to my mind was that there should be a way to automatically check this idle state, and if the user was in an idle state, create a new connection.

经过调试,我发现了一些新线索:“Supabase 的边缘节点/连接池(或者是操作系统,亦或是中间代理/NAT)在超时后会静默关闭那些空闲连接,但客户端连接池对此一无所知。”由于我当时没有进行任何操作,连接处于空闲状态,为了节省资源,服务器端静默关闭了该连接。当我再次尝试连接时,就出现了这个错误。我脑海中浮现的第一个想法是:应该有一种方法可以自动检测这种空闲状态,如果用户处于空闲状态,就创建一个新的连接。

Proposed Solutions: After a while, I came up with these solutions: Calculate the idle time: if it is more than the server connection timeout, then establish a new connection. Retry logic: retry once on specific connection errors. I thought this would work, but this again gave me an error, leading to this new issue I faced: the “Cold-start connection problem.”

提出的解决方案:经过一番思考,我想出了以下方案:计算空闲时间,如果超过了服务器连接超时时间,则建立新连接;重试逻辑,针对特定的连接错误进行一次重试。我原以为这样可行,但结果再次报错,从而引出了我面临的新问题:即“冷启动连接问题”。

There is something called dual-stack (IPv4 and IPv6) networks, and “Happy Eyeballs” is a network mechanism that automatically moves to an IPv4 connection if IPv6 fails. But supabase-py uses httpx, and it doesn’t support Happy Eyeballs. So, on the first try after the connection timeout, it tries to establish an IPv6 connection, which is not routable in most Pakistani ISPs, and ultimately it fails and waits for a timeout. There is no way to try it again for IPv4. So we have to do it manually. This error helped me learn many things in the process. Share your thoughts!

有一种东西叫双栈(IPv4 和 IPv6)网络,“Happy Eyeballs”是一种网络机制,如果 IPv6 连接失败,它会自动切换到 IPv4 连接。但 supabase-py 使用的是 httpx,它并不支持 Happy Eyeballs。因此,在连接超时后的第一次尝试中,它会尝试建立 IPv6 连接,而这在大多数巴基斯坦的 ISP 中是不可路由的,最终导致失败并等待超时。由于没有机制自动重试 IPv4,我们必须手动处理。这个错误让我在解决过程中学到了很多。欢迎分享你的想法!