Skip to content

Installation push tracking #2994

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 11 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion spec/helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ afterEach(function(done) {
} else {
// Other system classes will break Parse.com, so make sure that we don't save anything to _SCHEMA that will
// break it.
return ['_User', '_Installation', '_Role', '_Session', '_Product'].indexOf(className) >= 0;
return ['_User', '_Installation', '_Role', '_Session', '_Product', '_Push'].indexOf(className) >= 0;
}
}});
});
Expand Down
10 changes: 8 additions & 2 deletions src/Controllers/PushController.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,14 @@ export class PushController extends AdaptableController {
if (!response.results) {
return Promise.reject({error: 'PushController: no results in query'})
}
pushStatus.setRunning(response.results);
return this.sendToAdapter(body, response.results, pushStatus, config);
let installations = response.results;
pushStatus.setRunning(installations);
return this.sendToAdapter(body, response.results, pushStatus, config).then((results) => {
return {
installations,
results
};
});
}).then((results) => {
return pushStatus.complete(results);
}).catch((err) => {
Expand Down
10 changes: 8 additions & 2 deletions src/Controllers/SchemaController.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,12 @@ const defaultColumns = Object.freeze({
"title": {type:'String'},
"subtitle": {type:'String'},
},
_Push: {
"result": {type:'Object'},
"pushStatus": {type:'String'},
"installation": {type:'Pointer', targetClass:'_Installation'},
"deviceToken": {type:'String'},
},
_PushStatus: {
"pushTime": {type:'String'},
"source": {type:'String'}, // rest or webui
Expand Down Expand Up @@ -113,9 +119,9 @@ const requiredColumns = Object.freeze({
_Role: ["name", "ACL"]
});

const systemClasses = Object.freeze(['_User', '_Installation', '_Role', '_Session', '_Product', '_PushStatus', '_JobStatus']);
const systemClasses = Object.freeze(['_User', '_Installation', '_Role', '_Session', '_Product', '_Push', '_PushStatus', '_JobStatus']);

const volatileClasses = Object.freeze(['_JobStatus', '_PushStatus', '_Hooks', '_GlobalConfig']);
const volatileClasses = Object.freeze(['_JobStatus', '_PushStatus', '_Push', '_Hooks', '_GlobalConfig']);

// 10 alpha numberic chars + uppercase
const userIdRegex = /^[a-zA-Z0-9]{10}$/;
Expand Down
97 changes: 92 additions & 5 deletions src/StatusHandler.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { md5Hash, newObjectId } from './cryptoUtils';
import { logger } from './logger';
import _ from 'lodash';

const PUSH_STATUS_COLLECTION = '_PushStatus';
const JOB_STATUS_COLLECTION = '_JobStatus';
const PUSH_COLLECTION = '_Push';

export function flatten(array) {
return array.reduce((memo, element) => {
Expand Down Expand Up @@ -34,9 +36,84 @@ function statusHandler(className, database) {
return lastPromise;
}

function createPush(object) {
return database.create(PUSH_COLLECTION, object).then(() => {
return Promise.resolve(object);
});
}

function updatePush(query, updateFields) {
return database.update(PUSH_COLLECTION, query, updateFields);
}

function insertPushes(pushStatusObjectId, installations) {
// Insert a Push object for each installation we're pushing to
let now = new Date();
let promises = _.map(installations, installation => {
let pushObjectId = newObjectId();
let push = {
objectId: pushObjectId,
createdAt: now,
updatedAt: now,
deviceToken: installation.deviceToken,
installation: {
__type: 'Pointer',
className: "_Installation",
objectId: installation.objectId,
},
pushStatus: pushStatusObjectId
};
return createPush(push);
});
return Promise.all(promises);
}

function updatePushes(pushStatusObjectId, installations, results) {
let now = new Date();

let resultsByDeviceToken = _.keyBy(results, r => r.device.deviceToken);

// Update the push record for each installation
let promises = _.map(installations, installation => {
let deviceToken = installation.deviceToken;
let result = null;

// Handle different failure scenarios
if (!deviceToken) {
result = { transmitted: false, error: 'No deviceToken found on installation' }
} else if (deviceToken in resultsByDeviceToken) {
result = resultsByDeviceToken[deviceToken];
} else {
result = { transmitted: false, error: 'No result from adapter' }
}

// Find the record to update
let query = {
pushStatus: pushStatusObjectId,
installation: {
__type: 'Pointer',
className: "_Installation",
objectId: installation.objectId,
}
};
let updateFields = {
result: result,
updatedAt: now
};

return updatePush(query, updateFields);
});

return Promise.all(promises);
}

return Object.freeze({
create,
update
update,
createPush,
updatePush,
insertPushes,
updatePushes
})
}

Expand Down Expand Up @@ -138,11 +215,17 @@ export function pushStatusHandler(config) {

let setRunning = function(installations) {
logger.verbose('sending push to %d installations', installations.length);
return handler.update({status:"pending", objectId: objectId},
{status: "running", updatedAt: new Date() });
return handler.update({status:"pending", objectId: objectId},
{status: "running", updatedAt: new Date() }).then((result) => {
return handler.insertPushes(objectId, installations).then(() => {
return result;
});
});
}

let complete = function(results) {
let complete = function(data) {
let results = data.results;
let installations = data.installations;
let update = {
status: 'succeeded',
updatedAt: new Date(),
Expand Down Expand Up @@ -173,7 +256,11 @@ export function pushStatusHandler(config) {
}, update);
}
logger.verbose('sent push! %d success, %d failures', update.numSent, update.numFailed);
return handler.update({status:"running", objectId }, update);
return handler.update({status:"running", objectId }, update).then((result) => {
return handler.updatePushes(objectId, installations, results).then(() => {
return result;
});
});
}

let fail = function(err) {
Expand Down