Push: Cleanup invalid device tokens (#4149)
* Adds collecting invalid / expired device tokens from GCM / APNS * Cleanup invalid installations based on responses from the adapters * Adds test for cleanup * Adds tests for removal
This commit is contained in:
@@ -162,12 +162,13 @@ export function pushStatusHandler(config, objectId = newObjectId(config.objectId
|
||||
{status: "running", updatedAt: new Date(), count });
|
||||
}
|
||||
|
||||
const trackSent = function(results) {
|
||||
const trackSent = function(results, cleanupInstallations = process.env.PARSE_SERVER_CLEANUP_INVALID_INSTALLATIONS) {
|
||||
const update = {
|
||||
updatedAt: new Date(),
|
||||
numSent: 0,
|
||||
numFailed: 0
|
||||
};
|
||||
const devicesToRemove = [];
|
||||
if (Array.isArray(results)) {
|
||||
results = flatten(results);
|
||||
results.reduce((memo, result) => {
|
||||
@@ -181,6 +182,18 @@ export function pushStatusHandler(config, objectId = newObjectId(config.objectId
|
||||
if (result.transmitted) {
|
||||
memo.numSent++;
|
||||
} else {
|
||||
if (result && result.response && result.response.error && result.device && result.device.deviceToken) {
|
||||
const token = result.device.deviceToken;
|
||||
const error = result.response.error;
|
||||
// GCM errors
|
||||
if (error === 'NotRegistered' || error === 'InvalidRegistration') {
|
||||
devicesToRemove.push(token);
|
||||
}
|
||||
// APNS errors
|
||||
if (error === 'Unregistered') {
|
||||
devicesToRemove.push(token);
|
||||
}
|
||||
}
|
||||
memo.numFailed++;
|
||||
}
|
||||
return memo;
|
||||
@@ -189,7 +202,7 @@ export function pushStatusHandler(config, objectId = newObjectId(config.objectId
|
||||
}
|
||||
|
||||
logger.verbose(`_PushStatus ${objectId}: sent push! %d success, %d failures`, update.numSent, update.numFailed);
|
||||
|
||||
logger.verbose(`_PushStatus ${objectId}: needs cleanup`, { devicesToRemove });
|
||||
['numSent', 'numFailed'].forEach((key) => {
|
||||
if (update[key] > 0) {
|
||||
update[key] = {
|
||||
@@ -201,6 +214,14 @@ export function pushStatusHandler(config, objectId = newObjectId(config.objectId
|
||||
}
|
||||
});
|
||||
|
||||
if (devicesToRemove.length > 0 && cleanupInstallations) {
|
||||
logger.info(`Removing device tokens on ${devicesToRemove.length} _Installations`);
|
||||
database.update('_Installation', { deviceToken: { '$in': devicesToRemove }}, { deviceToken: {"__op": "Delete"} }, {
|
||||
acl: undefined,
|
||||
many: true
|
||||
});
|
||||
}
|
||||
|
||||
return handler.update({ objectId }, update).then((res) => {
|
||||
if (res && res.count === 0) {
|
||||
return this.complete();
|
||||
|
||||
Reference in New Issue
Block a user