chore: fix race condition with push iOS notification (#533)
This commit is contained in:
		
							parent
							
								
									7c7e740fec
								
							
						
					
					
						commit
						a4cc8d7582
					
				| 
						 | 
				
			
			@ -360,7 +360,7 @@ func getApnsClient(req PushNotification) (client *apns2.Client) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
// PushToIOS provide send notification to APNs server.
 | 
			
		||||
func PushToIOS(req PushNotification) bool {
 | 
			
		||||
func PushToIOS(req PushNotification) {
 | 
			
		||||
	LogAccess.Debug("Start push notification for iOS")
 | 
			
		||||
 | 
			
		||||
	var (
 | 
			
		||||
| 
						 | 
				
			
			@ -374,7 +374,6 @@ func PushToIOS(req PushNotification) bool {
 | 
			
		|||
 | 
			
		||||
Retry:
 | 
			
		||||
	var (
 | 
			
		||||
		isError   = false
 | 
			
		||||
		newTokens []string
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -386,12 +385,11 @@ Retry:
 | 
			
		|||
		// occupy push slot
 | 
			
		||||
		MaxConcurrentIOSPushes <- struct{}{}
 | 
			
		||||
		wg.Add(1)
 | 
			
		||||
		go func(token string) {
 | 
			
		||||
		go func(notification apns2.Notification, token string) {
 | 
			
		||||
			notification.DeviceToken = token
 | 
			
		||||
 | 
			
		||||
			// send ios notification
 | 
			
		||||
			res, err := client.Push(notification)
 | 
			
		||||
 | 
			
		||||
			res, err := client.Push(¬ification)
 | 
			
		||||
			if err != nil || (res != nil && res.StatusCode != http.StatusOK) {
 | 
			
		||||
				if err == nil {
 | 
			
		||||
					// error message:
 | 
			
		||||
| 
						 | 
				
			
			@ -418,27 +416,24 @@ Retry:
 | 
			
		|||
				if res != nil && res.StatusCode >= http.StatusInternalServerError {
 | 
			
		||||
					newTokens = append(newTokens, token)
 | 
			
		||||
				}
 | 
			
		||||
				isError = true
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if res != nil && res.Sent() && !isError {
 | 
			
		||||
			if res != nil && res.Sent() {
 | 
			
		||||
				LogPush(SucceededPush, token, req, nil)
 | 
			
		||||
				StatStorage.AddIosSuccess(1)
 | 
			
		||||
			}
 | 
			
		||||
			// free push slot
 | 
			
		||||
			<-MaxConcurrentIOSPushes
 | 
			
		||||
			wg.Done()
 | 
			
		||||
		}(token)
 | 
			
		||||
		}(*notification, token)
 | 
			
		||||
	}
 | 
			
		||||
	wg.Wait()
 | 
			
		||||
 | 
			
		||||
	if isError && retryCount < maxRetry {
 | 
			
		||||
	if len(newTokens) > 0 && retryCount < maxRetry {
 | 
			
		||||
		retryCount++
 | 
			
		||||
 | 
			
		||||
		// resend fail token
 | 
			
		||||
		req.Tokens = newTokens
 | 
			
		||||
		goto Retry
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return isError
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -706,14 +706,13 @@ func TestPushToIOS(t *testing.T) {
 | 
			
		|||
	assert.Nil(t, err)
 | 
			
		||||
 | 
			
		||||
	req := PushNotification{
 | 
			
		||||
		Tokens:   []string{"11aa01229f15f0f0c52029d8cf8cd0aeaf2365fe4cebc4af26cd6d76b7919ef7"},
 | 
			
		||||
		Tokens:   []string{"11aa01229f15f0f0c52029d8cf8cd0aeaf2365fe4cebc4af26cd6d76b7919ef7", "11aa01229f15f0f0c52029d8cf8cd0aeaf2365fe4cebc4af26cd6d76b7919ef1"},
 | 
			
		||||
		Platform: 1,
 | 
			
		||||
		Message:  "Welcome",
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// send fail
 | 
			
		||||
	isError := PushToIOS(req)
 | 
			
		||||
	assert.True(t, isError)
 | 
			
		||||
	PushToIOS(req)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestApnsHostFromRequest(t *testing.T) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -101,7 +101,7 @@ func GetAndroidNotification(req PushNotification) *fcm.Message {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
// PushToAndroid provide send notification to Android server.
 | 
			
		||||
func PushToAndroid(req PushNotification) bool {
 | 
			
		||||
func PushToAndroid(req PushNotification) {
 | 
			
		||||
	LogAccess.Debug("Start push notification for Android")
 | 
			
		||||
 | 
			
		||||
	var (
 | 
			
		||||
| 
						 | 
				
			
			@ -119,12 +119,10 @@ func PushToAndroid(req PushNotification) bool {
 | 
			
		|||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		LogError.Error("request error: " + err.Error())
 | 
			
		||||
		return false
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
Retry:
 | 
			
		||||
	var isError = false
 | 
			
		||||
 | 
			
		||||
	notification := GetAndroidNotification(req)
 | 
			
		||||
 | 
			
		||||
	if req.APIKey != "" {
 | 
			
		||||
| 
						 | 
				
			
			@ -136,14 +134,14 @@ Retry:
 | 
			
		|||
	if err != nil {
 | 
			
		||||
		// FCM server error
 | 
			
		||||
		LogError.Error("FCM server error: " + err.Error())
 | 
			
		||||
		return false
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	res, err := client.Send(notification)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		// Send Message error
 | 
			
		||||
		LogError.Error("FCM server send message error: " + err.Error())
 | 
			
		||||
		return false
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if !req.IsTopic() {
 | 
			
		||||
| 
						 | 
				
			
			@ -169,7 +167,6 @@ Retry:
 | 
			
		|||
			if !result.Unregistered() {
 | 
			
		||||
				newTokens = append(newTokens, to)
 | 
			
		||||
			}
 | 
			
		||||
			isError = true
 | 
			
		||||
 | 
			
		||||
			LogPush(FailedPush, to, req, result.Error)
 | 
			
		||||
			if PushConf.Core.Sync {
 | 
			
		||||
| 
						 | 
				
			
			@ -201,7 +198,6 @@ Retry:
 | 
			
		|||
		if res.MessageID != 0 {
 | 
			
		||||
			LogPush(SucceededPush, to, req, nil)
 | 
			
		||||
		} else {
 | 
			
		||||
			isError = true
 | 
			
		||||
			// failure
 | 
			
		||||
			LogPush(FailedPush, to, req, res.Error)
 | 
			
		||||
			if PushConf.Core.Sync {
 | 
			
		||||
| 
						 | 
				
			
			@ -212,7 +208,6 @@ Retry:
 | 
			
		|||
 | 
			
		||||
	// Device Group HTTP Response
 | 
			
		||||
	if len(res.FailedRegistrationIDs) > 0 {
 | 
			
		||||
		isError = true
 | 
			
		||||
		newTokens = append(newTokens, res.FailedRegistrationIDs...)
 | 
			
		||||
 | 
			
		||||
		LogPush(FailedPush, notification.To, req, errors.New("device group: partial success or all fails"))
 | 
			
		||||
| 
						 | 
				
			
			@ -221,13 +216,11 @@ Retry:
 | 
			
		|||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if isError && retryCount < maxRetry {
 | 
			
		||||
	if len(newTokens) > 0 && retryCount < maxRetry {
 | 
			
		||||
		retryCount++
 | 
			
		||||
 | 
			
		||||
		// resend fail token
 | 
			
		||||
		req.Tokens = newTokens
 | 
			
		||||
		goto Retry
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return isError
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -60,8 +60,7 @@ func TestPushToAndroidWrongToken(t *testing.T) {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	// Android Success count: 0, Failure count: 2
 | 
			
		||||
	isError := PushToAndroid(req)
 | 
			
		||||
	assert.True(t, isError)
 | 
			
		||||
	PushToAndroid(req)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestPushToAndroidRightTokenForJSONLog(t *testing.T) {
 | 
			
		||||
| 
						 | 
				
			
			@ -80,8 +79,7 @@ func TestPushToAndroidRightTokenForJSONLog(t *testing.T) {
 | 
			
		|||
		Message:  "Welcome",
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	isError := PushToAndroid(req)
 | 
			
		||||
	assert.False(t, isError)
 | 
			
		||||
	PushToAndroid(req)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestPushToAndroidRightTokenForStringLog(t *testing.T) {
 | 
			
		||||
| 
						 | 
				
			
			@ -98,8 +96,7 @@ func TestPushToAndroidRightTokenForStringLog(t *testing.T) {
 | 
			
		|||
		Message:  "Welcome",
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	isError := PushToAndroid(req)
 | 
			
		||||
	assert.False(t, isError)
 | 
			
		||||
	PushToAndroid(req)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestOverwriteAndroidAPIKey(t *testing.T) {
 | 
			
		||||
| 
						 | 
				
			
			@ -119,8 +116,7 @@ func TestOverwriteAndroidAPIKey(t *testing.T) {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	// FCM server error: 401 error: 401 Unauthorized (Wrong API Key)
 | 
			
		||||
	err := PushToAndroid(req)
 | 
			
		||||
	assert.False(t, err)
 | 
			
		||||
	PushToAndroid(req)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestFCMMessage(t *testing.T) {
 | 
			
		||||
| 
						 | 
				
			
			@ -215,8 +211,7 @@ func TestCheckAndroidMessage(t *testing.T) {
 | 
			
		|||
		TimeToLive: &timeToLive,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err := PushToAndroid(req)
 | 
			
		||||
	assert.False(t, err)
 | 
			
		||||
	PushToAndroid(req)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestAndroidNotificationStructure(t *testing.T) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue