使用firebase-admin SDK重试失败的FCM消息

问题描述

我正在为Go使用最新版本的firebase-admin-sdk,以便可以使用FCM发送推送通知。我已经建立了一个客户端,并且能够使用SendMultiCast()方法成功发送/接收通知

Firebase团队建议使用指数补偿方法实施重试以处理失败的请求。我设置了一个在较旧的FCM库中使用过的备用项。问题是我不确定在重试逻辑中应该处理哪种类型的错误以重播请求。我认为通常只在出现网络交付问题时才这样做。

这是基本的重试方法...我注释掉了其中的代码以寻找net.Errors,因为它似乎不像admin SDK那样返回。我知道SendMultiCast()方法返回一个错误一个BatchResponse错误响应是我应该重试的还是在BatchResponse中?我似乎在批处理响应中找不到要重试的内容

const (
    minBackoff = 100 * time.Millisecond
    maxBackoff = 1 * time.Minute
)

func retry(fn func() error,attempts int) error {
    var attempt int
    for {
        err := fn()
        log.Println("attempt to send")
        if err == nil {
            return nil
        }
        
        // This is what has worked in past libs since I Could expect 
        // net.errors signifying a timeout or some sort of http issue that would
        // require a retry
        // if tErr,ok := err.(net.Error); !ok || !tErr.Temporary() {
        //   return err
        // }

        attempt++
        backoff := minBackoff * time.Duration(attempt*attempt)

        if attempt > attempts || backoff > maxBackoff {
            return err
        }

        time.Sleep(backoff)
    }
}

下面是我尝试使用重试方式的摘要...

func (c *Client) Send(ctx context.Context,msg *messaging.MulticastMessage) (*FCMv1Response,error) {
    res := new(FCMv1Response)
    err := retry(func() error {
        ctx,cancel := context.WithTimeout(ctx,DefaultTimeout)
        defer cancel()
        var er error
        res.FailedTokens,er = c.sendMulticastMessage(ctx,msg)
        return er
    },RetryAttempts)

    if err != nil {
        c.logger.Error("errorSendingLLUNotification",zap.Error(err))
        return nil,err
    }
    return res,nil

}

func (c *Client) sendMulticastMessage(ctx context.Context,msg *messaging.MulticastMessage) ([]string,error) {
    br,err := c.msg.SendMulticast(ctx,msg)
    if err != nil {
        return nil,err
    }

    var FailedTokens []string
    if br.FailureCount > 0 {
        for idx,resp := range br.Responses {
            if !resp.Success {
                // The order of responses corresponds to the order of the registration tokens.
                FailedTokens = append(FailedTokens,msg.Tokens[idx])
            }
        }
    }
    return FailedTokens,nil
}

谢谢!

解决方法

DRAWITEMSTRUCT

您不必重试全部失败。 SDK会自动处理。在您的代码看到上述错误时,它已经被重试了几次而没有成功,或者该错误根本没有资格重试。

对于部分故障,messaging.SendResponse类型包含一个错误,可以通过dwItemData程序包或新的MENUITEMINFO程序包的错误处理功能传递该错误,以确定是否可以重试。通常,您只想在messaging.IsUnavailable()返回true的情况下重试。

您还需要确保重试仅发送到先前尝试中失败的令牌。在您上面提供的代码中,我看不到这种逻辑。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...