grocer: Socket connection drops next notification if invalid notification is sent
So, this is the problem I ran into on Lead Zeppelin (https://github.com/geoloqi/lead_zeppelin). It’s kindof a big problem right now, and I haven’t figured out a graceful way to fix it yet.
If you send an illegit message (such as a message with a bad device token), the connection will drop without throwing an exception for the next message, and that next message will effectively be dropped.
Example:
pusher = Grocer.pusher(certificate: "/path/to/validcert.pem")
notification = Grocer::Notification.new(device_token: "valid device token", alert: 'this will work')
pusher.push(notification)
notification = Grocer::Notification.new(device_token: "bad device token", alert: 'this will fail, as expected')
pusher.push(notification)
notification = Grocer::Notification.new(device_token: "valid device token", alert: 'THIS WILL UNEXPECTEDLY FAIL WITH NO EXCEPTIONS OR WARNINGS')
pusher.push(notification)
notification = Grocer::Notification.new(device_token: "valid device token", alert: 'this will work because an exception will be thrown, reconnecting the socket')
pusher.push(notification)
I don’t know what the source of this problem is… whether it’s something in Ruby, something on Apple’s APNS servers, or some sort of buffering issue, or what.
I worked around this problem by putting in an IO.select to wait for a specific period of time, to see if the socket becomes available for reading. With the enhanced protocol, being readable indicates that there was an error. But the only way to do this is to wait for a response before using it again, due to the silent failure. But this solution sucks, because it slows everything down.
You can see the implementation of that IO.select here: https://github.com/geoloqi/lead_zeppelin/blob/master/lib/lead_zeppelin/apns/gateway.rb#L96
The solution I was pondering to deal with this problem was to switch back to the version 0 protocol, but then of course you don’t get the enhanced error response, which also kindof sucks.
The real solution would be for APNS to send a confirmation bit like they should, or drop the connection correctly… but that’s not going to happen anytime soon. Really at a loss for how to solve this.
About this issue
- Original URL
- State: open
- Created 12 years ago
- Comments: 59 (27 by maintainers)
Commits related to this issue
- CHG: support socket timeout in Connection#open — committed to snow/houston by snow 9 years ago
Important Note
iOS 9.0 (and subsequent versions) introduced a subtle change to the way push tokens provided.
If you delete and then re-install an application the push token is invalidated and a new push token is generated. This is important because the feedback service does not deliver the list of invalidated tokens quickly enough to prevent you from using the now invalidated token.
There is currently a bug in grocer (#14) that will cause the APNS socket connect to hang up and fail to send subsequent notifications when one of these invalid tokens is used.
This bug combined with the change to push tokens in iOS results in varied reliability of push notification delivery. This may or may not affect you, but if you are seeing a large amount of undelivered notifications - specifically when sending multiple messages in quick succession - it is likely that you are coming up against this.
Right now we are looking for help moving over to Apple’s HTTP/2 notification endpoint which should address this situation, but the current maintainer doesn’t have time to do this work.
How’s this:
A WARNING TO APPLE SHARE CROPPERS
Using an Apple SDK to develop software for your livelihood is dangerous. They will give you a broken implementation of a broken protocol written by somebody that’s clearly never written an API before and has zero concept of error handling, then randomly add breaking changes to it, making your barely working broken implementation now 100% absolutely unusably broken. Expect everything to break, and expect Apple to not care or provide any way to communicate with the authors.
If you want to write reliable software, or software that doesn’t make you feel like you’re cooking soup for prisoners in a Siberian gulag, you should not under any circumstances develop software with an Apple SDK or API.