Skip to content

Commit cd16efc

Browse files
authored
Merge pull request #3219 from Countly/hotfix/push
Hotfix/push
2 parents af7b5b9 + b773532 commit cd16efc

File tree

7 files changed

+67
-16
lines changed

7 files changed

+67
-16
lines changed

plugins/push/api/api-auto.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,8 @@ module.exports.autoOnCohort = function(entry, cohort, uids) {
5353
logCohorts.d('processing %s %s, result: %j', typ, msg._id, result);
5454
if (result.total) {
5555
return msg.update({$inc: {'result.total': result.total}}, () => {
56-
result.total += result.total;
57-
}).then(() => Audience.resetQueue(result.next));
56+
msg.result.total += result.total;
57+
});
5858
}
5959
}).then(() => {
6060
logCohorts.d('done processing %s %s', typ, msg._id);

plugins/push/api/jobs/util/connector.js

+26-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
const { DoFinish } = require('./do_finish'),
2-
{ Message, State, Status, Creds, pools, FRAME, PushError, SendError, ERROR } = require('../../send'),
2+
{ Message, State, Status, Creds, pools, FRAME, PushError, SendError, ERROR, MAX_RUNS } = require('../../send'),
33
{ FRAME_NAME } = require('../../send/proto');
44

55
/**
@@ -21,6 +21,7 @@ class Connector extends DoFinish {
2121
this.db = db;
2222
this.state = state;
2323
this.limit = state.cfg.pool.pushes;
24+
this.connects = [];
2425
this.resetErrors();
2526
}
2627

@@ -31,6 +32,7 @@ class Connector extends DoFinish {
3132
this.noApp = new SendError('NoApp', ERROR.DATA_COUNTLY);
3233
this.noCreds = new SendError('NoCredentials', ERROR.DATA_COUNTLY);
3334
this.expiredCreds = new SendError('ExpiredCreds', ERROR.CONNECTION_PROVIDER);
35+
this.tooLateToSend = new SendError('TooLateToSend', ERROR.DATA_COUNTLY);
3436
this.noMessage = {}; // {mid: [push, push, push, ...]}
3537
this.noMessageBytes = 0;
3638
}
@@ -141,10 +143,17 @@ class Connector extends DoFinish {
141143
else { // all good with credentials, now let's check messages
142144
if (!message.is(State.Streaming)) {
143145
let date = new Date(),
144-
update = {$set: {status: Status.Sending, 'info.startedLast': date}, $bit: {state: {or: State.Streaming}}};
146+
update = {$set: {status: Status.Sending, 'info.startedLast': date}, $bit: {state: {or: State.Streaming}}},
147+
run = message.result.startRun(new Date());
145148
if (!message.info.started) {
146149
update.$set['info.started'] = date;
147150
}
151+
if (message.result.lastRuns.length === MAX_RUNS) {
152+
update.$set['result.lastRuns'] = message.result.lastRuns;
153+
}
154+
else {
155+
update.$push = {'result.lastRuns': run};
156+
}
148157
message.updateAtomically({_id: message._id, state: message.state}, update)
149158
.then(ok => {
150159
if (ok) {
@@ -155,6 +164,11 @@ class Connector extends DoFinish {
155164
}
156165
}, callback);
157166
}
167+
else if (push._id.getTimestamp().getTime() < Date.now() - 3600000) {
168+
this.tooLateToSend.addAffected(push._id, 1);
169+
this.do_flush(callback, true);
170+
return;
171+
}
158172
else {
159173
let creds = app.creds[push.p],
160174
pid = pools.id(creds.hash, push.p, push.f);
@@ -169,21 +183,24 @@ class Connector extends DoFinish {
169183
}
170184
else { // no connection yet
171185
this.log.i('Connecting %s', pid);
172-
pools.connect(push.a, push.p, push.f, creds, this.state, this.state.cfg).then(valid => {
186+
let connect = pools.connect(push.a, push.p, push.f, creds, this.state, this.state.cfg).then(valid => {
173187
if (valid) {
174188
this.log.i('Connected %s', pid);
175189
}
176190
else {
177191
app.creds[push.p] = null;
178192
}
193+
this.connects = this.connects.filter(c => c !== connect);
179194
callback(null, push);
180195
}, err => {
181196
this.log.i('Failed to connect %s', pid, err);
182197
app.creds[push.p] = null;
198+
this.connects = this.connects.filter(c => c !== connect);
183199
this.do_transform(push, encoding, callback);
184200
// this.discardedByAppOrCreds.push(push._id);
185201
// this.do_flush(callback, true);
186202
});
203+
this.connects.push(connect);
187204
}
188205
}
189206
}
@@ -196,7 +213,7 @@ class Connector extends DoFinish {
196213
* @param {boolean} ifNeeded true if we only need to flush `discarded` when it's length is over `limit`
197214
*/
198215
do_flush(callback, ifNeeded) {
199-
let total = this.noMessageBytes + this.noApp.affectedBytes + this.noCreds.affectedBytes + this.expiredCreds.affectedBytes;
216+
let total = this.noMessageBytes + this.noApp.affectedBytes + this.noCreds.affectedBytes + this.expiredCreds.affectedBytes + this.tooLateToSend.affectedBytes;
200217
this.log.d('in connector do_flush, total', total);
201218

202219
if (ifNeeded && !this.flushed && (!total || total < this.limit)) {
@@ -270,6 +287,10 @@ class Connector extends DoFinish {
270287
this.push({frame: FRAME.RESULTS | FRAME.ERROR, payload: this.expiredCreds});
271288
}
272289

290+
if (this.tooLateToSend.hasAffected) {
291+
this.push({frame: FRAME.RESULTS | FRAME.ERROR, payload: this.tooLateToSend});
292+
}
293+
273294
this.resetErrors();
274295

275296
callback();
@@ -375,7 +396,7 @@ class Connector extends DoFinish {
375396
* @param {function} callback callback function
376397
*/
377398
do_final(callback) {
378-
callback();
399+
Promise.all(this.connects).then(() => callback(), () => callback());
379400
}
380401

381402

plugins/push/api/jobs/util/resultor.js

+12
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,8 @@ class Resultor extends DoFinish {
113113

114114
if (msg) {
115115
result = msg.result;
116+
result.lastRun.processed++;
117+
result.lastRun.errored++;
116118
}
117119
else {
118120
result = this.noMessage[m] || (this.noMessage[m] = new Result());
@@ -166,6 +168,7 @@ class Resultor extends DoFinish {
166168

167169
if (m) {
168170
result = m.result;
171+
result.lastRun.processed++;
169172
}
170173
else {
171174
result = this.noMessage[m] || (this.noMessage[m] = new Result());
@@ -262,6 +265,13 @@ class Resultor extends DoFinish {
262265
result = this.noMessage[m] || (this.noMessage[m] = new Result());
263266
}
264267
result.processed[m] += mids[mid];
268+
269+
let run = result.lastRun;
270+
if (run) {
271+
run.processed += mids[mid];
272+
run.errored += mids[mid];
273+
}
274+
265275
result.pushError(error);
266276
this.data.decSending(mid);
267277
}
@@ -286,6 +296,8 @@ class Resultor extends DoFinish {
286296

287297
let updates = {},
288298
promises = this.data.messages().map(m => {
299+
m.result.lastRun.ended = new Date();
300+
289301
if (this.data.isSending(m.id)) {
290302
this.log.d('message %s is still in processing (%d out of %d)', m.id, m.result.processed, m.result.total);
291303
return m.save();

plugins/push/api/send/data/index.js

+5-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ const { S, State, Status, STATUSES, TriggerKind, MEDIA_MIME_ALL, MEDIA_MIME_IOS,
55
{ Creds } = require('./creds'),
66
{ Filter } = require('./filter'),
77
{ Content } = require('./content'),
8-
{ Result } = require('./result'),
8+
{ Result, MAX_ERRORS, MAX_RUNS } = require('./result'),
99
{ Message } = require('./message'),
1010
{ Template } = require('./template'),
1111
dbext = require('./db');
@@ -28,9 +28,12 @@ module.exports = {
2828

2929
Filter,
3030
Content,
31-
Result,
3231
Info,
3332

33+
Result,
34+
MAX_ERRORS,
35+
MAX_RUNS,
36+
3437
Message,
3538

3639
Template,

plugins/push/api/send/data/result.js

+20-6
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
'use strict';
22

33
const { PushError, ERROR } = require('./error'),
4-
{ toDate, Validatable } = require('./const');
4+
{ toDate, Validatable } = require('./const'),
5+
MAX_RUNS = 10,
6+
MAX_ERRORS = 10;
57

68
/**
79
* Message sending result
@@ -247,7 +249,7 @@ class Result extends Validatable {
247249
if (!this._data.lastErrors) {
248250
this._data.lastErrors = [];
249251
}
250-
while (this._data.lastErrors.length >= 10) {
252+
while (this._data.lastErrors.length >= MAX_ERRORS) {
251253
this._data.lastErrors.shift();
252254
}
253255
this._data.lastErrors.push(error);
@@ -280,6 +282,15 @@ class Result extends Validatable {
280282
return this._data.errors[code] = (this._data.errors[code] || 0) + count;
281283
}
282284

285+
/**
286+
* Getter for last of lastRuns
287+
*
288+
* @returns {object|undefined} last run object with start, processed, errored & end? keys
289+
*/
290+
get lastRun() {
291+
return this._data.lastRuns && this._data.lastRuns[this._data.lastRuns.length - 1] || undefined;
292+
}
293+
283294
/**
284295
* Getter for lastRuns
285296
*
@@ -292,16 +303,19 @@ class Result extends Validatable {
292303
/**
293304
* Add another run to lastRuns
294305
*
295-
* @param {object} run the run to push
306+
* @param {Date} date date of run start
307+
* @returns {object} run object with start, processed & errored props
296308
*/
297-
pushRun(run) {
309+
startRun(date) {
298310
if (!this._data.lastRuns) {
299311
this._data.lastRuns = [];
300312
}
301-
while (this._data.lastRuns.length >= 10) {
313+
while (this._data.lastRuns.length >= MAX_RUNS) {
302314
this._data.lastRuns.shift();
303315
}
316+
let run = {start: date, processed: 0, errored: 0};
304317
this._data.lastRuns.push(run);
318+
return run;
305319
}
306320

307321
/**
@@ -437,5 +451,5 @@ class Result extends Validatable {
437451

438452

439453

440-
module.exports = { Result };
454+
module.exports = { Result, MAX_RUNS, MAX_ERRORS };
441455

plugins/push/api/send/platforms/i.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -559,8 +559,8 @@ class APN extends Base {
559559
}
560560
if (this.creds instanceof CREDS.apn_token) {
561561
this.headersFirst.authorization = this.headersSecond.authorization = this.creds.bearer;
562-
this.headersFirst['apns-topic'] = this.headersSecond['apns-topic'] = this.creds._data.bundle;
563562
}
563+
this.headersFirst['apns-topic'] = this.headersSecond['apns-topic'] = this.creds._data.bundle;
564564
}
565565

566566
/**

plugins/push/frontend/public/localization/push.properties

+1
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,7 @@ push-notification.error-code.NoApp.desc = App not found when sending the notific
397397
push-notification.error-code.NoMessage.desc = The message was not found when sending the notification.
398398
push-notification.error-code.NoCredentials.desc = Push notification credentials were not found when sending the notification.
399399
push-notification.error-code.NoConnection.desc = Failed to connect to push notifications provider, please check APN / FCM / HPK are available from Countly host. In case you use proxy server, please check it's up and running.
400+
push-notification.error-code.TooLateToSend.desc = Countly was unable to send these notifications in time (1 hour from scheduled date).
400401
push-notification.error-code.ExpiredCreds.desc = Push Notification credentials have probably expired. Please upload new credentials.
401402
push-notification.error-code.BadDeviceToken.desc = The push token received from your app by Countly Server was rejected by APNS as invalid. Please make sure you set `pushTestMode` property on the SDK's initial configuration correctly. Also please make sure provisioning profile (Development or Distribution) is valid, bundle ID is correct and entitlements are properly set.
402403
push-notification.error-code.MissingTopic.desc = The server failed to parse the certificate, please ensure you use universal certificate and contact support if you do.

0 commit comments

Comments
 (0)