【发布时间】:2020-10-02 03:27:16
【问题描述】:
我正在为 Go 使用最新版本的 firebase-admin-sdk,以便我可以使用 FCM 发送推送通知。我已经构建了一个客户端,并且能够使用 SendMultiCast() 方法成功发送/接收通知。
Firebase 团队建议使用指数回退方法实施重试,以处理失败的请求。我已经设置了在旧 FCM 库中使用过的回退。问题是我不确定我应该在重试逻辑中处理哪种类型的错误以重播请求。我认为通常最好只在网络传输问题的情况下这样做。
这是基本的重试...我已经注释掉了其中寻找 net.Errors 的代码,因为管理 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)
}
}
下面是我如何尝试使用 Retry...
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
}
谢谢!
【问题讨论】:
标签: firebase go firebase-cloud-messaging firebase-admin