ToothlessGear / node-gcm

A NodeJS wrapper library port to send data to Android devices via Google Cloud Messaging
https://github.com/ToothlessGear/node-gcm
Other
1.3k stars 208 forks source link

Mysterious callback in my server #325

Closed saulogt closed 5 years ago

saulogt commented 5 years ago

Hi, I'm using this library to search for uninstalls of my android app. I noticed that after sending ~10k empty notifications, my server throughput increases substantially causing even some timeouts. I suspect there is a webhook setup somewhere in FCM configuration, but I'm not very familiar with it.

Am I doing it right?

The code looks very simple...

import gcm = require('node-gcm');
const gcmSender = new gcm.Sender(process.env.PUSH_ANDROID_API_KEY);

export function checkAndroidDeviceUninstalled(deviceToken: string) {
  // Prepare an empty message to be sent
  var message = new gcm.Message({
    data: {}
  });

  var regTokens = [deviceToken];
  return new Promise<Array<string | undefined>>((resolve, reject) => {
    gcmSender.sendNoRetry(message, { registrationTokens: regTokens }, function (err, response) {
      if (err) return reject(err);
      const uninstalled = (response.results as any[])                           // Array with result for each token we messaged
        .map((res, i) => {
          if (res.error) {
            if (res.error === 'NotRegistered' || res.error === 'MismatchSenderId') {
              return regTokens[i]
            } else if (res.error === 'InvalidRegistration') {
              console.error('InvalidRegistration', regTokens[i]);
            } else {
              throw new Error(`Unknown FCM error type '${res.error}'. ${regTokens}, ${message}`)
            }
          }
        })                                                             // pick _the token_ from the _other_ array
        .filter(token => token);
      resolve(uninstalled)
    });
  })
}
saulogt commented 5 years ago

It seems that I should do it with dryRun. Does it make sense?

eladnava commented 5 years ago

Looks like you are doing it right, I am not entirely sure the throughput issue is related to node-gcm.

Maybe you are parallelizing the work too much (i.e. too many concurrent calls to checkAndroidDeviceUninstalled())?

Make sure you are either executing serially or parallel but with a concurrent thread limit.

saulogt commented 5 years ago

It turned out that my app was calling the server back every time it received the notification, regardless of its content. As I just wanted to check for uninstall, setting dryRun solved the problem. Thanks!