Skip to content

Commit 2968fab

Browse files
authored
Merge pull request #140 from mixpanel/fix-notif-race
Replay events that were triggered prior to decide response
2 parents ab25112 + 8c0e91c commit 2968fab

File tree

13 files changed

+325
-156
lines changed

13 files changed

+325
-156
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
**2.29.1** (22 Aug 2019)
2+
- Fix race condition with event-triggered in-apps
3+
14
**2.29.0** (6 Jun 2019)
25
- `mixpanel.identify()` now sends special `$identify` event for advanced identity management
36
- Fix extraneous logging for Group API calls

build/mixpanel.amd.js

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ define(function () { 'use strict';
22

33
var Config = {
44
DEBUG: false,
5-
LIB_VERSION: '2.29.0'
5+
LIB_VERSION: '2.29.1'
66
};
77

88
// since es6 imports are static and we run unit tests from the console, window won't be defined when importing this file
@@ -3928,6 +3928,8 @@ define(function () { 'use strict';
39283928
instance['people']._init(instance);
39293929

39303930
instance._cached_groups = {}; // cache groups in a pool
3931+
instance._user_decide_check_complete = false;
3932+
instance._events_tracked_before_user_decide_check_complete = [];
39313933

39323934
// if any instance on the page has debug = true, we set the
39333935
// global debug to be true
@@ -4990,12 +4992,16 @@ define(function () { 'use strict';
49904992
};
49914993

49924994
MixpanelLib.prototype._check_and_handle_triggered_notifications = addOptOutCheckMixpanelLib(function(event_data) {
4993-
var arr = this['_triggered_notifs'];
4994-
for (var i = 0; i < arr.length; i++) {
4995-
var notif = new MPNotif(arr[i], this);
4996-
if (notif._matches_event_data(event_data)) {
4997-
this._show_notification(arr[i]);
4998-
return;
4995+
if (!this._user_decide_check_complete) {
4996+
this._events_tracked_before_user_decide_check_complete.push(event_data);
4997+
} else {
4998+
var arr = this['_triggered_notifs'];
4999+
for (var i = 0; i < arr.length; i++) {
5000+
var notif = new MPNotif(arr[i], this);
5001+
if (notif._matches_event_data(event_data)) {
5002+
this._show_notification(arr[i]);
5003+
return;
5004+
}
49995005
}
50005006
}
50015007
});
@@ -5032,10 +5038,22 @@ define(function () { 'use strict';
50325038
this._show_notification.call(this, notifications[0]);
50335039
}
50345040
}
5041+
this._handle_user_decide_check_complete();
50355042
}, this))
50365043
);
50375044
});
50385045

5046+
MixpanelLib.prototype._handle_user_decide_check_complete = function() {
5047+
this._user_decide_check_complete = true;
5048+
5049+
// check notifications against events that were tracked before decide call completed
5050+
var events = this._events_tracked_before_user_decide_check_complete;
5051+
while (events.length > 0) {
5052+
var data = events.shift(); // replay in the same order they came in
5053+
this._check_and_handle_triggered_notifications(data);
5054+
}
5055+
};
5056+
50395057
MixpanelLib.prototype._show_notification = function(notif_data) {
50405058
var notification = new MPNotif(notif_data, this);
50415059
notification.show();

build/mixpanel.cjs.js

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
var Config = {
44
DEBUG: false,
5-
LIB_VERSION: '2.29.0'
5+
LIB_VERSION: '2.29.1'
66
};
77

88
// since es6 imports are static and we run unit tests from the console, window won't be defined when importing this file
@@ -3928,6 +3928,8 @@ var create_mplib = function(token, config, name) {
39283928
instance['people']._init(instance);
39293929

39303930
instance._cached_groups = {}; // cache groups in a pool
3931+
instance._user_decide_check_complete = false;
3932+
instance._events_tracked_before_user_decide_check_complete = [];
39313933

39323934
// if any instance on the page has debug = true, we set the
39333935
// global debug to be true
@@ -4990,12 +4992,16 @@ MixpanelLib.prototype._event_is_disabled = function(event_name) {
49904992
};
49914993

49924994
MixpanelLib.prototype._check_and_handle_triggered_notifications = addOptOutCheckMixpanelLib(function(event_data) {
4993-
var arr = this['_triggered_notifs'];
4994-
for (var i = 0; i < arr.length; i++) {
4995-
var notif = new MPNotif(arr[i], this);
4996-
if (notif._matches_event_data(event_data)) {
4997-
this._show_notification(arr[i]);
4998-
return;
4995+
if (!this._user_decide_check_complete) {
4996+
this._events_tracked_before_user_decide_check_complete.push(event_data);
4997+
} else {
4998+
var arr = this['_triggered_notifs'];
4999+
for (var i = 0; i < arr.length; i++) {
5000+
var notif = new MPNotif(arr[i], this);
5001+
if (notif._matches_event_data(event_data)) {
5002+
this._show_notification(arr[i]);
5003+
return;
5004+
}
49995005
}
50005006
}
50015007
});
@@ -5032,10 +5038,22 @@ MixpanelLib.prototype._check_and_handle_notifications = addOptOutCheckMixpanelLi
50325038
this._show_notification.call(this, notifications[0]);
50335039
}
50345040
}
5041+
this._handle_user_decide_check_complete();
50355042
}, this))
50365043
);
50375044
});
50385045

5046+
MixpanelLib.prototype._handle_user_decide_check_complete = function() {
5047+
this._user_decide_check_complete = true;
5048+
5049+
// check notifications against events that were tracked before decide call completed
5050+
var events = this._events_tracked_before_user_decide_check_complete;
5051+
while (events.length > 0) {
5052+
var data = events.shift(); // replay in the same order they came in
5053+
this._check_and_handle_triggered_notifications(data);
5054+
}
5055+
};
5056+
50395057
MixpanelLib.prototype._show_notification = function(notif_data) {
50405058
var notification = new MPNotif(notif_data, this);
50415059
notification.show();

build/mixpanel.globals.js

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
var Config = {
55
DEBUG: false,
6-
LIB_VERSION: '2.29.0'
6+
LIB_VERSION: '2.29.1'
77
};
88

99
// since es6 imports are static and we run unit tests from the console, window won't be defined when importing this file
@@ -3929,6 +3929,8 @@
39293929
instance['people']._init(instance);
39303930

39313931
instance._cached_groups = {}; // cache groups in a pool
3932+
instance._user_decide_check_complete = false;
3933+
instance._events_tracked_before_user_decide_check_complete = [];
39323934

39333935
// if any instance on the page has debug = true, we set the
39343936
// global debug to be true
@@ -4991,12 +4993,16 @@
49914993
};
49924994

49934995
MixpanelLib.prototype._check_and_handle_triggered_notifications = addOptOutCheckMixpanelLib(function(event_data) {
4994-
var arr = this['_triggered_notifs'];
4995-
for (var i = 0; i < arr.length; i++) {
4996-
var notif = new MPNotif(arr[i], this);
4997-
if (notif._matches_event_data(event_data)) {
4998-
this._show_notification(arr[i]);
4999-
return;
4996+
if (!this._user_decide_check_complete) {
4997+
this._events_tracked_before_user_decide_check_complete.push(event_data);
4998+
} else {
4999+
var arr = this['_triggered_notifs'];
5000+
for (var i = 0; i < arr.length; i++) {
5001+
var notif = new MPNotif(arr[i], this);
5002+
if (notif._matches_event_data(event_data)) {
5003+
this._show_notification(arr[i]);
5004+
return;
5005+
}
50005006
}
50015007
}
50025008
});
@@ -5033,10 +5039,22 @@
50335039
this._show_notification.call(this, notifications[0]);
50345040
}
50355041
}
5042+
this._handle_user_decide_check_complete();
50365043
}, this))
50375044
);
50385045
});
50395046

5047+
MixpanelLib.prototype._handle_user_decide_check_complete = function() {
5048+
this._user_decide_check_complete = true;
5049+
5050+
// check notifications against events that were tracked before decide call completed
5051+
var events = this._events_tracked_before_user_decide_check_complete;
5052+
while (events.length > 0) {
5053+
var data = events.shift(); // replay in the same order they came in
5054+
this._check_and_handle_triggered_notifications(data);
5055+
}
5056+
};
5057+
50405058
MixpanelLib.prototype._show_notification = function(notif_data) {
50415059
var notification = new MPNotif(notif_data, this);
50425060
notification.show();

build/mixpanel.umd.js

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
var Config = {
88
DEBUG: false,
9-
LIB_VERSION: '2.29.0'
9+
LIB_VERSION: '2.29.1'
1010
};
1111

1212
// since es6 imports are static and we run unit tests from the console, window won't be defined when importing this file
@@ -3932,6 +3932,8 @@
39323932
instance['people']._init(instance);
39333933

39343934
instance._cached_groups = {}; // cache groups in a pool
3935+
instance._user_decide_check_complete = false;
3936+
instance._events_tracked_before_user_decide_check_complete = [];
39353937

39363938
// if any instance on the page has debug = true, we set the
39373939
// global debug to be true
@@ -4994,12 +4996,16 @@
49944996
};
49954997

49964998
MixpanelLib.prototype._check_and_handle_triggered_notifications = addOptOutCheckMixpanelLib(function(event_data) {
4997-
var arr = this['_triggered_notifs'];
4998-
for (var i = 0; i < arr.length; i++) {
4999-
var notif = new MPNotif(arr[i], this);
5000-
if (notif._matches_event_data(event_data)) {
5001-
this._show_notification(arr[i]);
5002-
return;
4999+
if (!this._user_decide_check_complete) {
5000+
this._events_tracked_before_user_decide_check_complete.push(event_data);
5001+
} else {
5002+
var arr = this['_triggered_notifs'];
5003+
for (var i = 0; i < arr.length; i++) {
5004+
var notif = new MPNotif(arr[i], this);
5005+
if (notif._matches_event_data(event_data)) {
5006+
this._show_notification(arr[i]);
5007+
return;
5008+
}
50035009
}
50045010
}
50055011
});
@@ -5036,10 +5042,22 @@
50365042
this._show_notification.call(this, notifications[0]);
50375043
}
50385044
}
5045+
this._handle_user_decide_check_complete();
50395046
}, this))
50405047
);
50415048
});
50425049

5050+
MixpanelLib.prototype._handle_user_decide_check_complete = function() {
5051+
this._user_decide_check_complete = true;
5052+
5053+
// check notifications against events that were tracked before decide call completed
5054+
var events = this._events_tracked_before_user_decide_check_complete;
5055+
while (events.length > 0) {
5056+
var data = events.shift(); // replay in the same order they came in
5057+
this._check_and_handle_triggered_notifications(data);
5058+
}
5059+
};
5060+
50435061
MixpanelLib.prototype._show_notification = function(notif_data) {
50445062
var notification = new MPNotif(notif_data, this);
50455063
notification.show();

examples/commonjs-browserify/bundle.js

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
var Config = {
55
DEBUG: false,
6-
LIB_VERSION: '2.29.0'
6+
LIB_VERSION: '2.29.1'
77
};
88

99
// since es6 imports are static and we run unit tests from the console, window won't be defined when importing this file
@@ -3929,6 +3929,8 @@ var create_mplib = function(token, config, name) {
39293929
instance['people']._init(instance);
39303930

39313931
instance._cached_groups = {}; // cache groups in a pool
3932+
instance._user_decide_check_complete = false;
3933+
instance._events_tracked_before_user_decide_check_complete = [];
39323934

39333935
// if any instance on the page has debug = true, we set the
39343936
// global debug to be true
@@ -4991,12 +4993,16 @@ MixpanelLib.prototype._event_is_disabled = function(event_name) {
49914993
};
49924994

49934995
MixpanelLib.prototype._check_and_handle_triggered_notifications = addOptOutCheckMixpanelLib(function(event_data) {
4994-
var arr = this['_triggered_notifs'];
4995-
for (var i = 0; i < arr.length; i++) {
4996-
var notif = new MPNotif(arr[i], this);
4997-
if (notif._matches_event_data(event_data)) {
4998-
this._show_notification(arr[i]);
4999-
return;
4996+
if (!this._user_decide_check_complete) {
4997+
this._events_tracked_before_user_decide_check_complete.push(event_data);
4998+
} else {
4999+
var arr = this['_triggered_notifs'];
5000+
for (var i = 0; i < arr.length; i++) {
5001+
var notif = new MPNotif(arr[i], this);
5002+
if (notif._matches_event_data(event_data)) {
5003+
this._show_notification(arr[i]);
5004+
return;
5005+
}
50005006
}
50015007
}
50025008
});
@@ -5033,10 +5039,22 @@ MixpanelLib.prototype._check_and_handle_notifications = addOptOutCheckMixpanelLi
50335039
this._show_notification.call(this, notifications[0]);
50345040
}
50355041
}
5042+
this._handle_user_decide_check_complete();
50365043
}, this))
50375044
);
50385045
});
50395046

5047+
MixpanelLib.prototype._handle_user_decide_check_complete = function() {
5048+
this._user_decide_check_complete = true;
5049+
5050+
// check notifications against events that were tracked before decide call completed
5051+
var events = this._events_tracked_before_user_decide_check_complete;
5052+
while (events.length > 0) {
5053+
var data = events.shift(); // replay in the same order they came in
5054+
this._check_and_handle_triggered_notifications(data);
5055+
}
5056+
};
5057+
50405058
MixpanelLib.prototype._show_notification = function(notif_data) {
50415059
var notification = new MPNotif(notif_data, this);
50425060
notification.show();

examples/es2015-babelify/bundle.js

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -732,7 +732,7 @@ Object.defineProperty(exports, '__esModule', {
732732
});
733733
var Config = {
734734
DEBUG: false,
735-
LIB_VERSION: '2.29.0'
735+
LIB_VERSION: '2.29.1'
736736
};
737737

738738
exports['default'] = Config;
@@ -1790,6 +1790,8 @@ var create_mplib = function create_mplib(token, config, name) {
17901790
instance['people']._init(instance);
17911791

17921792
instance._cached_groups = {}; // cache groups in a pool
1793+
instance._user_decide_check_complete = false;
1794+
instance._events_tracked_before_user_decide_check_complete = [];
17931795

17941796
// if any instance on the page has debug = true, we set the
17951797
// global debug to be true
@@ -2855,12 +2857,16 @@ MixpanelLib.prototype._event_is_disabled = function (event_name) {
28552857
};
28562858

28572859
MixpanelLib.prototype._check_and_handle_triggered_notifications = (0, _gdprUtils.addOptOutCheckMixpanelLib)(function (event_data) {
2858-
var arr = this['_triggered_notifs'];
2859-
for (var i = 0; i < arr.length; i++) {
2860-
var notif = new MPNotif(arr[i], this);
2861-
if (notif._matches_event_data(event_data)) {
2862-
this._show_notification(arr[i]);
2863-
return;
2860+
if (!this._user_decide_check_complete) {
2861+
this._events_tracked_before_user_decide_check_complete.push(event_data);
2862+
} else {
2863+
var arr = this['_triggered_notifs'];
2864+
for (var i = 0; i < arr.length; i++) {
2865+
var notif = new MPNotif(arr[i], this);
2866+
if (notif._matches_event_data(event_data)) {
2867+
this._show_notification(arr[i]);
2868+
return;
2869+
}
28642870
}
28652871
}
28662872
});
@@ -2890,9 +2896,21 @@ MixpanelLib.prototype._check_and_handle_notifications = (0, _gdprUtils.addOptOut
28902896
this._show_notification.call(this, notifications[0]);
28912897
}
28922898
}
2899+
this._handle_user_decide_check_complete();
28932900
}, this)));
28942901
});
28952902

2903+
MixpanelLib.prototype._handle_user_decide_check_complete = function () {
2904+
this._user_decide_check_complete = true;
2905+
2906+
// check notifications against events that were tracked before decide call completed
2907+
var events = this._events_tracked_before_user_decide_check_complete;
2908+
while (events.length > 0) {
2909+
var data = events.shift(); // replay in the same order they came in
2910+
this._check_and_handle_triggered_notifications(data);
2911+
}
2912+
};
2913+
28962914
MixpanelLib.prototype._show_notification = function (notif_data) {
28972915
var notification = new MPNotif(notif_data, this);
28982916
notification.show();

0 commit comments

Comments
 (0)