Closed pcompassion closed 7 years ago
@pcompassion, APNS should recover the connection on next message sending, please let me know if it doesn't, thanks :)
I must be doing something wrong then.
I tried send_message_frame
below, and it won't send push after it encounters a bogus registration_id.
I find some ios devices don't receive push notification when using send_message
but I have no idea how to start debugging..
if settings.DEBUG:
use_sandbox = True
else:
use_sandbox = False
APNS_CERTIFICATE_COMBINED = settings.PUSH_NOTIFICATIONS_SETTINGS['APNS_CERTIFICATE_COMBINED']
# https://github.com/djacobs/PyAPNs/issues/108
apns = APNs(use_sandbox=use_sandbox, cert_file=APNS_CERTIFICATE_COMBINED, enhanced=True)
def send_message_frame(self, message, **kwargs):
frame = Frame()
expiry = time.time() + 3600
priority = 10
payload = Payload(
alert=message, sound=kwargs.pop("sound", "default"),
custom=kwargs.pop("extra", None)
)
for registration_id in self.values_list("registration_id", flat=True):
try:
identifier = registration_id
frame.add_item(registration_id, payload, identifier, expiry, priority)
- except TypeError:
logger.exception("apns typeerror")
pass
apns.gateway_server.send_notification_multiple(frame)
def send_message(self, message, **kwargs):
payload = Payload(
alert=message, sound=kwargs.pop("sound", "default"),
custom=kwargs.pop("extra", None)
)
# for registration_id in self.values_list("registration_id", flat=True):
for device in self.all():
registration_id = device.registration_id
identifier = device.id
try:
apns.gateway_server.send_notification(registration_id, payload, identifier=identifier)
except TypeError:
# (3297, u'UIUserNotificationSettings:0x1702\
# 28ca0;types:(none);')
# self.filter(id=device.id).delete()
logger.exception("apns typeerror")
@pcompassion , your identifier must be unique for each message in order to let PyAPNs identify which message to re-send, please refer to https://github.com/djacobs/PyAPNs#enhanced-message-with-immediate-error-response , the document might not clear enough, which is already address in this PR #128
I tried unique identifier (fixed the above code).
I'd like to see something like got error-response from APNS:(8, 1) rebuilding connection to APNS resending 9 notifications to APNS resending notification with id:2 to APNS resending notification with id:3 to APNS resending notification with id:4 to APNS
But I don't see any logging messages, I only know some of the devices which have valid registration_id didn't receive push notification (when using bulk-send) I know his registration-id is fine because I can send a push-notification when he is the only recipient.
From your answer, it seems I shouldn't see someone who has a legitamate registration_id not receiving push, but I do see such case.
How should I go about debugging it?
@pcompassion , Thanks for your feedbacks,
ios_sent_queue.update({notification_id: reg_id})
, so I can find the reg-id of the failed message and conduct re-send.FYR
@jimhorng Can you share the code of how you did the mapping?
@kjvenky, My example for maintain sent message and reg_id
def _handle_ios_error_response(error_response):
status_code = error_response[apns.ER_STATUS]
notification_id = error_response[apns.ER_IDENTIFER]
do_some_error_handling
ios_sent_queue = OrderedDict()
MAX_QUEUE = 100000
apns_sender = apns.APNs()
apns_sender.gateway_server.register_response_listener(_handle_ios_error_response)
if len(ios_sent_queue) >= MAX_QUEUE:
ios_sent_queue.popitem(last=False)
ios_sent_queue.update({notification_id: reg_id})
@jimhorng the issue with this is at this line "do_some_error_handling" I am not able to able to map reg_id to the notifications_id in the _handle_iso_error_response. Did you try that? I want to mark the red_ids as invalid in the data base. Where are you sending the notifications in this. Any other urls with sample you know?
@kjvenky ,
as you can see at ios_sent_queue.update({notification_id: reg_id})
, it maintains a notification id and reg_id mapping, so that you can just ios_sent_queue[notification_id]
to get reg_id
, and then query for reg_id
in DB to update relevant data :)
I think in this case it works well because in the error handling function will look in the next scope level which has the mapping.
I am trying to put notification sending in a separate send_notification(mapping is defined in this) function in which case there is no way to pass the mapping from the send_notification to the ios_response_handler
Hey I figured out. I think i should just define a function in a function like this:
def send_notifictions():
def ios_handler:
# Do handling of errors
# Send notifications
@jimhorng Any suggestions on how to collect all these errors in async and do something on all of them at once?
When there's a bad token, or connection is broken for other reasons, there seems to be a way to recover it.
I'm struggling to google how I should implement the
recovery
.Wouldn't it be nice to include howto-recover-from-error in the readme?