RADAR-base/RADAR-Appserver

[FEAT] Delete user token and associated notifications on DEVICE UNREGISTER event

yatharthranjan opened this issue · 5 comments

Is your feature request related to a problem? Please describe.
There are several errors when sending notifications because the devices could be unregistered and there is no handling of this error code.

Describe the solution you'd like
When a notification is sent to a device that is unregistered, FCM SDK reports its error code. This can be used to delete the FCM token for the user and also delete any scheduled notifications for them

The change can be added here

will also require adding a parameter of type Message to handleFCMErrorCode so can get details on the user from

.

Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.

Priority
2

Difficulty
3

Additional context
Relevant Logs-

2021-06-25 17:30:00,112 ERROR [quartzScheduler_Worker-3] org.radarbase.appserver.service.scheduler.NotificationSchedulerService: Error occurred when sending downstream message.
com.google.firebase.messaging.FirebaseMessagingException: Requested entity was not found.
	at com.google.firebase.messaging.FirebaseMessagingException.withMessagingErrorCode(FirebaseMessagingException.java:47)
	at com.google.firebase.messaging.FirebaseMessagingClientImpl$MessagingErrorHandler.createException(FirebaseMessagingClientImpl.java:293)
	at com.google.firebase.messaging.FirebaseMessagingClientImpl$MessagingErrorHandler.createException(FirebaseMessagingClientImpl.java:282)
	at com.google.firebase.internal.AbstractHttpErrorHandler.handleHttpResponseException(AbstractHttpErrorHandler.java:57)
	at com.google.firebase.internal.ErrorHandlingHttpClient.send(ErrorHandlingHttpClient.java:108)
	at com.google.firebase.internal.ErrorHandlingHttpClient.sendAndParse(ErrorHandlingHttpClient.java:72)
	at com.google.firebase.messaging.FirebaseMessagingClientImpl.sendSingleRequest(FirebaseMessagingClientImpl.java:127)
	at com.google.firebase.messaging.FirebaseMessagingClientImpl.send(FirebaseMessagingClientImpl.java:113)
	at com.google.firebase.messaging.FirebaseMessaging$1.execute(FirebaseMessaging.java:135)
	at com.google.firebase.messaging.FirebaseMessaging$1.execute(FirebaseMessaging.java:132)
	at com.google.firebase.internal.CallableOperation.call(CallableOperation.java:36)
	at com.google.firebase.messaging.FirebaseMessaging.send(FirebaseMessaging.java:102)
	at com.google.firebase.messaging.FirebaseMessaging.send(FirebaseMessaging.java:86)
	at org.radarbase.fcm.downstream.AdminSdkFcmSender.send(AdminSdkFcmSender.java:117)
	at org.radarbase.appserver.service.scheduler.NotificationSchedulerService.send(NotificationSchedulerService.java:97)
	at org.radarbase.appserver.service.scheduler.quartz.MessageJob.execute(MessageJob.java:91)
	at org.quartz.core.JobRunShell.run(JobRunShell.java:202)
	at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573)
Caused by: com.google.api.client.http.HttpResponseException: 404 Not Found
POST https://fcm.googleapis.com/v1/projects/radar-armt-notification/messages:send
{
  "error": {
    "code": 404,
    "message": "Requested entity was not found.",
    "status": "NOT_FOUND",
    "details": [
      {
        "@type": "type.googleapis.com/google.firebase.fcm.v1.FcmError",
        "errorCode": "UNREGISTERED"
      }
    ]
  }
}

	at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:1113)
	at com.google.firebase.internal.ErrorHandlingHttpClient.send(ErrorHandlingHttpClient.java:96)
	... 13 common frames omitted
stale commented

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

We have received similar messages, with response message:

{
  "error": {
    "message": "The registration token is not a valid FCM registration token",
    "status": "INVALID_ARGUMENT",
    "details": [
      {
        "@type": "type.googleapis.com/google.firebase.fcm.v1.FcmError",
        "errorCode": "INVALID_ARGUMENT"
      }
    ]
  }
}

I'm wondering if whenever an app gets updated / reinstalled, also the FCM token gets updated or that we will send messages to the old app and those will not arrive. It would help to add the project ID and user ID to the log messages, to be able to debug which messages failed to deliver.

I think in your case this could be due to an invalid token (like an empty string)? Are you getting this very frequently and what version of appserver are you on?

The issue mentioned here was fixed already in #263 and now we delete all the notifications/data messages for the user and remove the fcm token whenever a DEVICE UNREGISTER error is received (code is here).

We're not getting it frequently, but we're missing some notifications for a particular user, and we get this error message is at the same time that the notification should have arrived. So either the questionnaire app did not correctly update the FCM token or the Appserver didn't. In particular, I'm not sure about this code:

public void checkFcmTokenExistsAndReplace(FcmUserDto userDto) {
. Does it actually update the FCM token correctly if the user logs in again, for example after reinstalling?

This function just updates the FCM token to an invalid value when a DEVICE UNREGISTER error is received. This adds a timestamp as the token so it can be investigated. All the notifications are deleted before the token is invalidated.
The app will update the FCM token for the user whenever it is updated on the client app.