-
Notifications
You must be signed in to change notification settings - Fork 44
Description
In 11.x and previous versions, the fetch-http2 library would issue HTTP/2 PING frames if the keepAlive option was set (by calling the node:http2 Http2Session.ping method).
However, undici does not implement HTTP/2 PING frames at all. The keepalive option on undici's Pool just sends TCP keepalive, not HTTP/2 keepalive.
Apple's documentation for APNs best practices explicitly states that PING frames can be sent to keep the connection open if it has not been used for an hour. Just sending TCP keepalive is apparently not enough.
In the last two weeks, Apple has started not responding to connections that have been open for a long time without sending PINGs.
We see this clearly when using a server that opens long-lived connections to APNs - messages are sent fine for several hours, followed by a several hour break. After the break, Apple stops responding to our messages.
When using @parse/node-apn, this returns with an error that there has been a timeout. However, this package doesn't implement a timeout, so the call to await client.send() blocks forever.
Blocking forever, waiting for a response that will never come, seems like a major problem to me.
I don't think there's a way to hook into undici at a low enough level to send PING frames, but I'm trying to figure out which of these makes the most sense:
- Move back off of
unidicito yourfetch-http2library again - this would lose the built-in connection pooling - Try to get
undicito implement HTTP/2 PING - not sure what is the level of effort and the time frame to do that - Temporary Workaround - use
undiciPool'sclientTtloption to prevent clients from lasting longer than an hour. This goes against Apple's recommendations, but would probably prevent the issue from happening until a more permanent fix can be done. (Also, this is a newundicifeature that was added last week and has not been released yet.)
Thoughts?