Skip to content

Commit 4f982e0

Browse files
chore: ensure data from any previous 'queue-bug' event is included in newer report
1 parent 235145b commit 4f982e0

3 files changed

Lines changed: 99 additions & 38 deletions

File tree

libraries/o-tracking/src/javascript/core/send.js

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -137,18 +137,31 @@ function run(callback = function () { /* empty */}) {
137137
// Investigate queue lengths bug
138138
// https://jira.ft.com/browse/DTP-330
139139
const all_events = queue.all();
140+
let queue_length = all_events.length;
140141

141-
if (all_events.length > 200) {
142+
if (queue_length > 200) {
142143
const counts = {};
143144

144-
all_events.forEach(function (event) {
145-
const label = [event.category, event.action].join(':');
146-
147-
if (!Object.prototype.hasOwnProperty.call(counts, label)) {
148-
counts[label] = 0;
145+
all_events.forEach(function ({
146+
category,
147+
action,
148+
context: {counts: event_counts = {}} = {},
149+
}) {
150+
// If a previously-queued event was a 'queue-bug' summary,
151+
// extract the information and add to the current context
152+
if (category === 'o-tracking' && action === 'queue-bug') {
153+
for (const [label, count] of Object.entries(event_counts)) {
154+
counts[label] = (counts[label] || 0) + count;
155+
queue_length += count;
156+
}
157+
158+
// Data from this old 'queue-bug' event has been exported,
159+
// so the event can now be forgotten
160+
queue_length -= 1;
161+
} else {
162+
const label = [category, action].join(':');
163+
counts[label] = (counts[label] || 0) + 1;
149164
}
150-
151-
counts[label] += 1;
152165
});
153166

154167
queue.replace([]);
@@ -158,10 +171,10 @@ function run(callback = function () { /* empty */}) {
158171
action: 'queue-bug',
159172
context: {
160173
url: document.URL,
161-
queue_length: all_events.length,
174+
queue_length,
162175
counts: counts,
163-
storage: queue.storage.storage._type
164-
}
176+
storage: queue.storage.storage._type,
177+
},
165178
});
166179
}
167180

@@ -210,9 +223,4 @@ function init() {
210223
return queue;
211224
}
212225

213-
export {
214-
init,
215-
add,
216-
run,
217-
addAndRun
218-
};
226+
export {init, addAndRun};

libraries/o-tracking/test/core.test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import sinon from 'sinon/pkg/sinon-esm.js';
55
import {set, destroy} from '../src/javascript/core/settings.js';
66
import {Queue} from '../src/javascript/core/queue.js';
77
import {session, init} from '../src/javascript/core/session.js';
8-
import {init as initSend, run} from '../src/javascript/core/send.js';
8+
import {init as initSend} from '../src/javascript/core/send.js';
99
import core from '../src/javascript/core.js';
1010
import { errorNextSend } from './setup.js';
1111

@@ -100,7 +100,7 @@ describe('Core', function () {
100100
proclaim.equal(callback.called, 1, 'Callback called once.');
101101

102102
// Try again
103-
run();
103+
initSend();
104104

105105
proclaim.ok(callback.calledOnce, 'Callback should only be called once as next send could be on a different page.');
106106
});

libraries/o-tracking/test/core/send.test.js

Lines changed: 72 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ import proclaim from 'proclaim';
44
import sinon from 'sinon/pkg/sinon-esm.js';
55
import {
66
init,
7-
add,
87
addAndRun
98
} from '../../src/javascript/core/send.js';
109
import {Queue} from "../../src/javascript/core/queue.js";
1110
import {unmockTransport, mockTransport} from '../setup.js';
1211
import {set, destroy} from '../../src/javascript/core/settings.js';
12+
import {mock} from '../../src/javascript/core/transports/index.js';
1313

1414
const request = {
1515
id: '1.199.83760034665465.1432907605043.-56cf00f',
@@ -51,13 +51,6 @@ describe('Core.Send', function () {
5151
});
5252
});
5353

54-
it('should add a request', function () {
55-
proclaim.doesNotThrow(function () {
56-
add(request);
57-
});
58-
});
59-
60-
6154
describe('fallback transports', function () {
6255
before(function () {
6356
unmockTransport();
@@ -252,13 +245,18 @@ describe('Core.Send', function () {
252245
});
253246

254247
describe('queue bug', function () {
248+
let queue;
255249
let transport;
250+
let transportError = false;
256251

257252
beforeEach(function () {
253+
set('config', {queue: true});
254+
queue = init();
255+
258256
transport = {
259257
send: sinon.spy(),
260258
complete: function (callback) {
261-
callback();
259+
callback(transportError);
262260
},
263261
};
264262

@@ -267,28 +265,30 @@ describe('Core.Send', function () {
267265
};
268266
});
269267

270-
it('should cope with the huge queue bug', function (done) {
271-
let queue = new Queue('requests');
268+
afterEach(function () {
269+
queue.storage.destroy();
270+
});
272271

273-
queue.replace([]);
272+
it('should summarise large numbers of offline events to avoid the huge queue bug', function () {
273+
// Simulate offline
274+
transportError = true;
274275

275276
for (let i = 0; i < 200; i++) {
276-
queue.add({
277+
addAndRun({
277278
category: 'page',
278279
action: 'view',
279280
});
280281
}
281282

282-
queue.add({
283+
// Go online, and send the events with a clean sinon.spy history
284+
transportError = false;
285+
transport.send.resetHistory();
286+
287+
addAndRun({
283288
category: 'button',
284289
action: 'click',
285290
});
286291

287-
queue.save();
288-
289-
// Run the queue
290-
init();
291-
292292
// Only one event should be sent
293293
proclaim.equal(transport.send.callCount, 1);
294294

@@ -300,6 +300,59 @@ describe('Core.Send', function () {
300300
'page:view': 200,
301301
'button:click': 1,
302302
});
303+
304+
proclaim.equal(queue.all().length, 0);
305+
});
306+
307+
it('should summarise all offline events rather than discard previous summaries', function () {
308+
// Simulate offline
309+
transportError = true;
310+
311+
// queue up 200 events
312+
for (let i = 0; i < 200; i++) {
313+
addAndRun({
314+
category: 'page',
315+
action: 'view',
316+
});
317+
}
318+
319+
// try - and fail - to send the events
320+
addAndRun({
321+
category: 'button',
322+
action: 'click',
323+
});
324+
325+
// queue up 200 more events
326+
for (let i = 0; i < 200; i++) {
327+
addAndRun({
328+
category: 'page',
329+
action: 'view',
330+
});
331+
}
332+
333+
// Go online, and send the events with a clean sinon.spy history
334+
transportError = false;
335+
transport.send.resetHistory();
336+
337+
338+
addAndRun({
339+
category: 'button',
340+
action: 'click',
341+
});
342+
343+
// Two send events should have been attempted
344+
proclaim.equal(transport.send.callCount, 2);
345+
346+
const payload = JSON.parse(transport.send.secondCall.args[1]);
347+
proclaim.equal(payload.category, 'o-tracking');
348+
proclaim.equal(payload.action, 'queue-bug');
349+
proclaim.equal(payload.context.queue_length, 401);
350+
proclaim.deepEqual(payload.context.counts, {
351+
'page:view': 400,
352+
'button:click': 2,
353+
});
354+
355+
proclaim.equal(queue.all().length, 0);
303356
});
304357
});
305358
});

0 commit comments

Comments
 (0)