PyAPNs and the need to Sleep between Sends

人盡茶涼 提交于 2019-12-08 02:04:25

问题


I am using PyAPNs to send notifications to iOS devices. I am often sending groups of notifications at once. If any of the tokens is bad for any reason, the process will stop. As a result I am using the enhanced setup and the following method:

apns.gateway_server.register_response_listener

I use this to track which token was the problem and then I pick up from there sending the rest. The issue is that when sending the only way to trap these errors is to use a sleep timer between token sends. For example:

for x in self.retryAPNList:
   apns.gateway_server.send_notification(x, payload, identifier = token)
   time.sleep(0.5)

If I don't use a sleep timer no errors are caught and thus my entire APN list is not sent to as the process stops when there is a bad token. However, this sleep timer is somewhat arbitrary. Sometimes the .5 seconds is enough while other times I have had to set it to 1. In no case has it worked without some sleep delay being added. Doing this slows down web calls and it feels less than bullet proof to enter random sleep times.

Any suggestions for how this can work without a delay between APN calls or is there a best practice for the delay needed?

Adding more code due to the request made below. Here are 3 methods inside of a class that I use to control this:

class PushAdmin(webapp2.RequestHandler):

    retryAPNList=[]
    channelID=""
    channelName = ""
    userName=""

    apns = APNs(use_sandbox=True,cert_file="mycert.pem", key_file="mykey.pem", enhanced=True)

    def devChannelPush(self,channel,name,sendAlerts):
        ucs = UsedChannelStore()
        pus = PushUpdateStore()
        channelName = ""
        refreshApnList = pus.getAPN(channel)
        if sendAlerts:
            alertApnList,channelName = ucs.getAPN(channel)
            if not alertApnList: alertApnList=[]
            if not refreshApnList: refreshApnList=[]
            pushApnList = list(set(alertApnList+refreshApnList))
        elif refreshApnList:
            pushApnList = refreshApnList
        else:
            pushApnList = []

        self.retryAPNList = pushApnList
        self.channelID = channel
        self.channelName = channelName
        self.userName = name
        self.retryAPNPush()

    def retryAPNPush(self):
        token = -1
        payload = Payload(alert="A message from " +self.userName+ " posted to "+self.channelName, sound="default", badge=1, custom={"channel":self.channelID})

        if len(self.retryAPNList)>0:
            token +=1
            for x in self.retryAPNList:
                    self.apns.gateway_server.send_notification(x, payload, identifier = token)
                    time.sleep(0.5)

Below is the calling class (abbreviate to reduce non-related items):

class ChannelStore(ndb.Model):
   def writeMessage(self,ID,name,message,imageKey,fileKey):
        notify = PushAdmin()

        notify.devChannelPush(ID,name,True)

Below is the slight change I made to the placement of the sleep timer that seems to have resolved the issue. I am, however, still concerned for whether the time given will be the right amount in all circumstances.

def retryAPNPush(self):
        identifier = 1
        token = -1
        payload = Payload(alert="A message from " +self.userName+ " posted to "+self.channelName, sound="default", badge=1, custom={"channel":self.channelID})

        if len(self.retryAPNList)>0:
            token +=1
            for x in self.retryAPNList:
                self.apns.gateway_server.send_notification(x, payload, identifier = token)
            time.sleep(0.5)

Resolution:

As noted in the comments at bottom, the resolution to this problem was to move the following statement to the module level outside the class. By doing this there is no need for any sleep statements.

apns = APNs(use_sandbox=True,cert_file="mycert.pem", key_file="mykey.pem", enhanced=True)

回答1:


In fact, PyAPNS will auto resend dropped notifications for you, please see PyAPNS

So you don't have to retry by yourself, you can just record what notifications have bad tokens.

The behavior of your code might be result from APNS object kept in local scope (within if len(self.retryAPNList)>0:)

I suggest you to pull out APNS object to class or module level, so that it can complete its error handling procedure and reuse the TCP connection.

Please kindly let me know if it helps, thanks :)



来源:https://stackoverflow.com/questions/29178740/pyapns-and-the-need-to-sleep-between-sends

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!