timehop / apns

A Go package to interface with the Apple Push Notification Service
https://godoc.org/github.com/timehop/apns
MIT License
185 stars 47 forks source link

[feature request] Notification of success #16

Closed nathany closed 9 years ago

nathany commented 9 years ago

When receiving an error-response packet with a status code of 0 (No errors encountered), does it just ignore that?

I'm thinking that I'd like to send "success" over FaildNotifs (probably renamed). Essentially, I'm trying to wrap a synchronous API around this low-level socket stuff so that my REST API can return an appropriate status code.

Right now I'd be waiting on FailedNotif with a timeout, and if nothing shows up, assume success.

I'd probably keep that behaviour, but if I get back 0 (No errors encountered), I can stop waiting for the timeout and just return 200 OK right away.

What do you think?

taylortrimble commented 9 years ago

I'd be very surprised to see a return value of 0 in practice, but I certainly don't see that return value being filtered out anywhere in the code.

If you'd like to build that functionality into your app, I'd say you have everything you need.

nathany commented 9 years ago

I failed to read this part:

If you send a notification that is accepted by APNs, nothing is returned.

https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/CommunicatingWIthAPS.html#//apple_ref/doc/uid/TP40008194-CH101-SW1

nathany commented 9 years ago

That makes a synchronous API rather difficult, doesn't it?

I don't really want to sit waiting for a timeout.

I've been testing with a 1 second timeout and sometimes errors come back from Apple after that timeout expires. Even a 1 second timeout could significantly slow things down. Hrm.

taylortrimble commented 9 years ago

You wouldn't want to anyway: it would really damage the performance of your service!

The "synchronous API" planned by @bdotdub in #17 is, necessarily, a synchronous Send method. And it will do exactly that; report if the message is successfully sent to APNS. It cannot make any guarantees about whether or not the message was accepted by the APNS service, nor if it was delivered to or accepted by the app.

No matter what, you don't want a synchronous delivery API for APNS; your users phones are not connected to the internet at all times! And due to a QOS queue of size 1, it is not sufficient to assume that "no error from APNS" means that message will reach your app.

This means the only way to know a message was delivered and correctly handled by your application is to have your iOS app send your service an application-defined acknowledgement. If guaranteed delivery/processing is important, you'll need to retry delivery. This would probably have to involve some very large timeout (not one second), with back-off and a circuit breaker.

The simplest thing you can do is try to loosen your requirements. Does the notification need to reach the phone? You have a lot of work to do (storage of messages, application acknowledgement, retry, back-off, and circuit-breaker logic). Not really? Then just call Send and forget about it. This is the use case APNS is truly designed for.

No matter what, synchronous Send is possible (#17) and even desirable, since it gives us the flexibility to define our own concurrency in our service, but synchronous SendAndEnsureDeliveryAndProcessing is a much more difficult issue that will require application logic.

taylortrimble commented 9 years ago

FYI, if you'd like some more help with this topic, I'd be happy to give you more detailed pointers. My team and I did have a hard requirement for guaranteed delivery, and did implement the system described above, but combined with an out-of-band delivery mechanism to avoid pummeling APNS.

Reach out to me by email if you're interested in further details!

nathany commented 9 years ago

@tylrtrmbl Thanks. I actually wasn't going for "SendAndEnsureDeliveryAndProcessing".

I just was hoping for a synchronous error response for bad sends (ErrInvalidToken, etc.). I don't know if that (#17) is really possible, not without a timeout that would at some point assume no error. But I don't want that delay.

And yes, no error doesn't mean delivery is guaranteed, that's fine for what I need (for now).

Now I'm thinking of a different API that will work fine with FailedNotifs as is.

taylortrimble commented 9 years ago

Okay, cool. Yeah, we're pretty much limited to Send in this case. SendAndGuaranteeAPNSProcessing would definitely require a nasty heuristically-determined timeout... but it's such a thin guarantee anyway.

Glad you found a way to change your API to not have to deal with that nightmare; you're lucky to avoid reliable delivery!