【问题标题】:PyAPNs and the need to Sleep between SendsPyAPNs 和发送之间睡眠的需要
【发布时间】:2015-03-21 02:56:40
【问题描述】:

我正在使用 PyAPNs 向 iOS 设备发送通知。我经常一次发送多组通知。如果任何令牌因任何原因而损坏,则该过程将停止。因此,我正在使用增强设置和以下方法:

apns.gateway_server.register_response_listener

我使用它来跟踪哪个令牌是问题,然后我从那里接收发送其余的令牌。问题是发送时捕获这些错误的唯一方法是在令牌发送之间使用睡眠计时器。例如:

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

如果我不使用睡眠计时器,则不会捕获任何错误,因此当出现错误令牌时进程停止时,我的整个 APN 列表不会被发送到。然而,这个睡眠定时器有些随意。有时 0.5 秒就足够了,而其他时候我不得不将它设置为 1。在没有添加一些睡眠延迟的情况下,它无论如何都无法工作。这样做会减慢网络通话速度,并且进入随机睡眠时间感觉不那么安全。

关于如何在 APN 调用之间无延迟地工作的任何建议,或者是否有针对所需延迟的最佳实践?

由于以下请求而添加更多代码。以下是我用来控制它的类中的 3 个方法:

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)

下面是调用类(缩写以减少无关项):

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

        notify.devChannelPush(ID,name,True)

以下是我对睡眠定时器的位置所做的细微更改,似乎已经解决了这个问题。然而,我仍然担心给予的时间是否在所有情况下都是正确的。

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)

分辨率:

正如底部的 cmets 所述,解决此问题的方法是将以下语句移至类外的模块级别。这样就不需要任何睡眠语句。

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

【问题讨论】:

  • 这是贡献者之一,我可以看到更多完整的代码sn-p吗?包括apns是怎么构造的,retryAPNList是怎么处理的,为了排查问题,谢谢:)
  • 感谢您的回复。我在上面的 OP 中添加了更多代码。

标签: python ios apple-push-notifications pyapns


【解决方案1】:

实际上,PyAPNS 会自动为您重新发送丢弃的通知,请参阅PyAPNS

所以你不必自己重试,你只需记录哪些通知有坏令牌。

您的代码的行为可能是由于 APNS 对象保留在本地范围内(if len(self.retryAPNList)>0: 内)

我建议你把APNS对象拉到类或模块级别,这样它就可以完成它的错误处理过程并重用TCP连接。

如果有帮助请告诉我,谢谢:)

【讨论】:

  • 你说得对,我可以从重新发送的角度移除监听器。但是,如果不添加睡眠延迟,该过程仍然无法工作。根据您的建议,我将 APNS 对象移至类级别,因此在您引用的 if 语句之后,我将其称为“self.apns”。结果是相同的,没有引入延迟。我正在使用 2 个令牌进行测试,第一个是坏的,第二个是好的。没有延迟添加第二个令牌永远不会发送,因为它会挂在第一个令牌上。当我添加延迟时,第二个发送非常快。
  • @C6Silver 你能发布日志吗?谢谢:)
  • 以及整个代码,包括如何调用类?谢谢:)
  • 我重新编辑了我上面的帖子,以包含您请求的代码以及调用。但是,我不知道要包括哪些日志。我在 Google 的 App Engine 上使用它,并且该过程不会抛出错误以包含在此处。
  • @C6Silver 我猜循环在没有睡眠的情况下很快结束,因为您只发送了一些通知,然后 PushAdmin() 对象在 ChannelStore.writeMessage() 完成时结束。您可以尝试让 ChannelStore.writeMessage() 运行更长的时间,以查看是否正在处理 bad-token 通知,或者如果它不够清晰,我们可以返回 github,以便更容易粘贴代码进行讨论:)
猜你喜欢
  • 2013-11-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-18
  • 2014-09-11
  • 2015-10-13
  • 2014-06-20
  • 2023-03-26
相关资源
最近更新 更多