Skip to content

Commit 2c8b47e

Browse files
committed
Merge branch 'v2.42.0-rc'
2 parents 7749a81 + 987fd6a commit 2c8b47e

File tree

16 files changed

+464
-541
lines changed

16 files changed

+464
-541
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/build
22
node_modules
33
npm-debug.log
4+
tunnel.log
45
.idea
56
.jshintignore
67
.jshintrc

dist/mixpanel.amd.js

Lines changed: 28 additions & 43 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.41.0'
5+
LIB_VERSION: '2.42.0-rc2'
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
@@ -1684,28 +1684,6 @@ define(function () { 'use strict';
16841684
return maxlen ? guid.substring(0, maxlen) : guid;
16851685
};
16861686

1687-
/**
1688-
* Check deterministically whether to include or exclude from a feature rollout/test based on the
1689-
* given string and the desired percentage to include.
1690-
* @param {String} str - string to run the check against (for instance a project's token)
1691-
* @param {String} feature - name of feature (for inclusion in hash, to ensure different results
1692-
* for different features)
1693-
* @param {Number} percent_allowed - percentage chance that a given string will be included
1694-
* @returns {Boolean} whether the given string should be included
1695-
*/
1696-
var determine_eligibility = _.safewrap(function(str, feature, percent_allowed) {
1697-
str = str + feature;
1698-
1699-
// Bernstein's hash: http://www.cse.yorku.ca/~oz/hash.html#djb2
1700-
var hash = 5381;
1701-
for (var i = 0; i < str.length; i++) {
1702-
hash = ((hash << 5) + hash) + str.charCodeAt(i);
1703-
hash = hash & hash;
1704-
}
1705-
var dart = (hash >>> 0) % 100;
1706-
return dart < percent_allowed;
1707-
});
1708-
17091687
// naive way to extract domain name (example.com) from full hostname (my.sub.example.com)
17101688
var SIMPLE_DOMAIN_MATCH_REGEX = /[a-z0-9][a-z0-9-]*\.[a-z]+$/i;
17111689
// this next one attempts to account for some ccSLDs, e.g. extracting oxford.ac.uk from www.oxford.ac.uk
@@ -2444,9 +2422,9 @@ define(function () { 'use strict';
24442422
} else if (
24452423
_.isObject(res) &&
24462424
res.xhr_req &&
2447-
(res.xhr_req['status'] >= 500 || res.xhr_req['status'] <= 0)
2425+
(res.xhr_req['status'] >= 500 || res.xhr_req['status'] === 429 || res.error === 'timeout')
24482426
) {
2449-
// network or API error, retry
2427+
// network or API error, or 429 Too Many Requests, retry
24502428
var retryMS = this.flushInterval * 2;
24512429
var headers = res.xhr_req['responseHeaders'];
24522430
if (headers) {
@@ -5924,7 +5902,7 @@ define(function () { 'use strict';
59245902
'inapp_protocol': '//',
59255903
'inapp_link_new_window': false,
59265904
'ignore_dnt': false,
5927-
'batch_requests': false, // for now
5905+
'batch_requests': true,
59285906
'batch_size': 50,
59295907
'batch_flush_interval_ms': 5000,
59305908
'batch_request_timeout_ms': 90000,
@@ -6043,17 +6021,7 @@ define(function () { 'use strict';
60436021
this['config'] = {};
60446022
this['_triggered_notifs'] = [];
60456023

6046-
// rollout: enable batch_requests by default for 60% of projects
6047-
// (only if they have not specified a value in their init config
6048-
// and they aren't using a custom API host)
6049-
var variable_features = {};
6050-
var api_host = config['api_host'];
6051-
var is_custom_api = !!api_host && !api_host.match(/\.mixpanel\.com$/);
6052-
if (!('batch_requests' in config) && !is_custom_api && determine_eligibility(token, 'batch', 60)) {
6053-
variable_features['batch_requests'] = true;
6054-
}
6055-
6056-
this.set_config(_.extend({}, DEFAULT_CONFIG, variable_features, config, {
6024+
this.set_config(_.extend({}, DEFAULT_CONFIG, config, {
60576025
'name': name,
60586026
'token': token,
60596027
'callback_fn': ((name === PRIMARY_INSTANCE_NAME) ? name : PRIMARY_INSTANCE_NAME + '.' + name) + '._jsc'
@@ -6079,15 +6047,32 @@ define(function () { 'use strict';
60796047
} else {
60806048
this.init_batchers();
60816049
if (sendBeacon && window$1.addEventListener) {
6082-
window$1.addEventListener('unload', _.bind(function() {
6083-
// Before page closes, attempt to flush any events queued up via navigator.sendBeacon.
6084-
// Since sendBeacon doesn't report success/failure, events will not be removed from
6085-
// the persistent store; if the site is loaded again, the events will be flushed again
6086-
// on startup and deduplicated on the Mixpanel server side.
6050+
// Before page closes or hides (user tabs away etc), attempt to flush any events
6051+
// queued up via navigator.sendBeacon. Since sendBeacon doesn't report success/failure,
6052+
// events will not be removed from the persistent store; if the site is loaded again,
6053+
// the events will be flushed again on startup and deduplicated on the Mixpanel server
6054+
// side.
6055+
// There is no reliable way to capture only page close events, so we lean on the
6056+
// visibilitychange and pagehide events as recommended at
6057+
// https://developer.mozilla.org/en-US/docs/Web/API/Window/unload_event#usage_notes.
6058+
// These events fire when the user clicks away from the current page/tab, so will occur
6059+
// more frequently than page unload, but are the only mechanism currently for capturing
6060+
// this scenario somewhat reliably.
6061+
var flush_on_unload = _.bind(function() {
60876062
if (!this.request_batchers.events.stopped) {
60886063
this.request_batchers.events.flush({unloading: true});
60896064
}
6090-
}, this));
6065+
}, this);
6066+
window$1.addEventListener('pagehide', function(ev) {
6067+
if (ev['persisted']) {
6068+
flush_on_unload();
6069+
}
6070+
});
6071+
window$1.addEventListener('visibilitychange', function() {
6072+
if (document$1['visibilityState'] === 'hidden') {
6073+
flush_on_unload();
6074+
}
6075+
});
60916076
}
60926077
}
60936078
}

dist/mixpanel.cjs.js

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

33
var Config = {
44
DEBUG: false,
5-
LIB_VERSION: '2.41.0'
5+
LIB_VERSION: '2.42.0-rc2'
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
@@ -1684,28 +1684,6 @@ var cheap_guid = function(maxlen) {
16841684
return maxlen ? guid.substring(0, maxlen) : guid;
16851685
};
16861686

1687-
/**
1688-
* Check deterministically whether to include or exclude from a feature rollout/test based on the
1689-
* given string and the desired percentage to include.
1690-
* @param {String} str - string to run the check against (for instance a project's token)
1691-
* @param {String} feature - name of feature (for inclusion in hash, to ensure different results
1692-
* for different features)
1693-
* @param {Number} percent_allowed - percentage chance that a given string will be included
1694-
* @returns {Boolean} whether the given string should be included
1695-
*/
1696-
var determine_eligibility = _.safewrap(function(str, feature, percent_allowed) {
1697-
str = str + feature;
1698-
1699-
// Bernstein's hash: http://www.cse.yorku.ca/~oz/hash.html#djb2
1700-
var hash = 5381;
1701-
for (var i = 0; i < str.length; i++) {
1702-
hash = ((hash << 5) + hash) + str.charCodeAt(i);
1703-
hash = hash & hash;
1704-
}
1705-
var dart = (hash >>> 0) % 100;
1706-
return dart < percent_allowed;
1707-
});
1708-
17091687
// naive way to extract domain name (example.com) from full hostname (my.sub.example.com)
17101688
var SIMPLE_DOMAIN_MATCH_REGEX = /[a-z0-9][a-z0-9-]*\.[a-z]+$/i;
17111689
// this next one attempts to account for some ccSLDs, e.g. extracting oxford.ac.uk from www.oxford.ac.uk
@@ -2444,9 +2422,9 @@ RequestBatcher.prototype.flush = function(options) {
24442422
} else if (
24452423
_.isObject(res) &&
24462424
res.xhr_req &&
2447-
(res.xhr_req['status'] >= 500 || res.xhr_req['status'] <= 0)
2425+
(res.xhr_req['status'] >= 500 || res.xhr_req['status'] === 429 || res.error === 'timeout')
24482426
) {
2449-
// network or API error, retry
2427+
// network or API error, or 429 Too Many Requests, retry
24502428
var retryMS = this.flushInterval * 2;
24512429
var headers = res.xhr_req['responseHeaders'];
24522430
if (headers) {
@@ -5924,7 +5902,7 @@ var DEFAULT_CONFIG = {
59245902
'inapp_protocol': '//',
59255903
'inapp_link_new_window': false,
59265904
'ignore_dnt': false,
5927-
'batch_requests': false, // for now
5905+
'batch_requests': true,
59285906
'batch_size': 50,
59295907
'batch_flush_interval_ms': 5000,
59305908
'batch_request_timeout_ms': 90000,
@@ -6043,17 +6021,7 @@ MixpanelLib.prototype._init = function(token, config, name) {
60436021
this['config'] = {};
60446022
this['_triggered_notifs'] = [];
60456023

6046-
// rollout: enable batch_requests by default for 60% of projects
6047-
// (only if they have not specified a value in their init config
6048-
// and they aren't using a custom API host)
6049-
var variable_features = {};
6050-
var api_host = config['api_host'];
6051-
var is_custom_api = !!api_host && !api_host.match(/\.mixpanel\.com$/);
6052-
if (!('batch_requests' in config) && !is_custom_api && determine_eligibility(token, 'batch', 60)) {
6053-
variable_features['batch_requests'] = true;
6054-
}
6055-
6056-
this.set_config(_.extend({}, DEFAULT_CONFIG, variable_features, config, {
6024+
this.set_config(_.extend({}, DEFAULT_CONFIG, config, {
60576025
'name': name,
60586026
'token': token,
60596027
'callback_fn': ((name === PRIMARY_INSTANCE_NAME) ? name : PRIMARY_INSTANCE_NAME + '.' + name) + '._jsc'
@@ -6079,15 +6047,32 @@ MixpanelLib.prototype._init = function(token, config, name) {
60796047
} else {
60806048
this.init_batchers();
60816049
if (sendBeacon && window$1.addEventListener) {
6082-
window$1.addEventListener('unload', _.bind(function() {
6083-
// Before page closes, attempt to flush any events queued up via navigator.sendBeacon.
6084-
// Since sendBeacon doesn't report success/failure, events will not be removed from
6085-
// the persistent store; if the site is loaded again, the events will be flushed again
6086-
// on startup and deduplicated on the Mixpanel server side.
6050+
// Before page closes or hides (user tabs away etc), attempt to flush any events
6051+
// queued up via navigator.sendBeacon. Since sendBeacon doesn't report success/failure,
6052+
// events will not be removed from the persistent store; if the site is loaded again,
6053+
// the events will be flushed again on startup and deduplicated on the Mixpanel server
6054+
// side.
6055+
// There is no reliable way to capture only page close events, so we lean on the
6056+
// visibilitychange and pagehide events as recommended at
6057+
// https://developer.mozilla.org/en-US/docs/Web/API/Window/unload_event#usage_notes.
6058+
// These events fire when the user clicks away from the current page/tab, so will occur
6059+
// more frequently than page unload, but are the only mechanism currently for capturing
6060+
// this scenario somewhat reliably.
6061+
var flush_on_unload = _.bind(function() {
60876062
if (!this.request_batchers.events.stopped) {
60886063
this.request_batchers.events.flush({unloading: true});
60896064
}
6090-
}, this));
6065+
}, this);
6066+
window$1.addEventListener('pagehide', function(ev) {
6067+
if (ev['persisted']) {
6068+
flush_on_unload();
6069+
}
6070+
});
6071+
window$1.addEventListener('visibilitychange', function() {
6072+
if (document$1['visibilityState'] === 'hidden') {
6073+
flush_on_unload();
6074+
}
6075+
});
60916076
}
60926077
}
60936078
}

dist/mixpanel.globals.js

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

44
var Config = {
55
DEBUG: false,
6-
LIB_VERSION: '2.41.0'
6+
LIB_VERSION: '2.42.0-rc2'
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
@@ -1685,28 +1685,6 @@
16851685
return maxlen ? guid.substring(0, maxlen) : guid;
16861686
};
16871687

1688-
/**
1689-
* Check deterministically whether to include or exclude from a feature rollout/test based on the
1690-
* given string and the desired percentage to include.
1691-
* @param {String} str - string to run the check against (for instance a project's token)
1692-
* @param {String} feature - name of feature (for inclusion in hash, to ensure different results
1693-
* for different features)
1694-
* @param {Number} percent_allowed - percentage chance that a given string will be included
1695-
* @returns {Boolean} whether the given string should be included
1696-
*/
1697-
var determine_eligibility = _.safewrap(function(str, feature, percent_allowed) {
1698-
str = str + feature;
1699-
1700-
// Bernstein's hash: http://www.cse.yorku.ca/~oz/hash.html#djb2
1701-
var hash = 5381;
1702-
for (var i = 0; i < str.length; i++) {
1703-
hash = ((hash << 5) + hash) + str.charCodeAt(i);
1704-
hash = hash & hash;
1705-
}
1706-
var dart = (hash >>> 0) % 100;
1707-
return dart < percent_allowed;
1708-
});
1709-
17101688
// naive way to extract domain name (example.com) from full hostname (my.sub.example.com)
17111689
var SIMPLE_DOMAIN_MATCH_REGEX = /[a-z0-9][a-z0-9-]*\.[a-z]+$/i;
17121690
// this next one attempts to account for some ccSLDs, e.g. extracting oxford.ac.uk from www.oxford.ac.uk
@@ -2445,9 +2423,9 @@
24452423
} else if (
24462424
_.isObject(res) &&
24472425
res.xhr_req &&
2448-
(res.xhr_req['status'] >= 500 || res.xhr_req['status'] <= 0)
2426+
(res.xhr_req['status'] >= 500 || res.xhr_req['status'] === 429 || res.error === 'timeout')
24492427
) {
2450-
// network or API error, retry
2428+
// network or API error, or 429 Too Many Requests, retry
24512429
var retryMS = this.flushInterval * 2;
24522430
var headers = res.xhr_req['responseHeaders'];
24532431
if (headers) {
@@ -5925,7 +5903,7 @@
59255903
'inapp_protocol': '//',
59265904
'inapp_link_new_window': false,
59275905
'ignore_dnt': false,
5928-
'batch_requests': false, // for now
5906+
'batch_requests': true,
59295907
'batch_size': 50,
59305908
'batch_flush_interval_ms': 5000,
59315909
'batch_request_timeout_ms': 90000,
@@ -6044,17 +6022,7 @@
60446022
this['config'] = {};
60456023
this['_triggered_notifs'] = [];
60466024

6047-
// rollout: enable batch_requests by default for 60% of projects
6048-
// (only if they have not specified a value in their init config
6049-
// and they aren't using a custom API host)
6050-
var variable_features = {};
6051-
var api_host = config['api_host'];
6052-
var is_custom_api = !!api_host && !api_host.match(/\.mixpanel\.com$/);
6053-
if (!('batch_requests' in config) && !is_custom_api && determine_eligibility(token, 'batch', 60)) {
6054-
variable_features['batch_requests'] = true;
6055-
}
6056-
6057-
this.set_config(_.extend({}, DEFAULT_CONFIG, variable_features, config, {
6025+
this.set_config(_.extend({}, DEFAULT_CONFIG, config, {
60586026
'name': name,
60596027
'token': token,
60606028
'callback_fn': ((name === PRIMARY_INSTANCE_NAME) ? name : PRIMARY_INSTANCE_NAME + '.' + name) + '._jsc'
@@ -6080,15 +6048,32 @@
60806048
} else {
60816049
this.init_batchers();
60826050
if (sendBeacon && window$1.addEventListener) {
6083-
window$1.addEventListener('unload', _.bind(function() {
6084-
// Before page closes, attempt to flush any events queued up via navigator.sendBeacon.
6085-
// Since sendBeacon doesn't report success/failure, events will not be removed from
6086-
// the persistent store; if the site is loaded again, the events will be flushed again
6087-
// on startup and deduplicated on the Mixpanel server side.
6051+
// Before page closes or hides (user tabs away etc), attempt to flush any events
6052+
// queued up via navigator.sendBeacon. Since sendBeacon doesn't report success/failure,
6053+
// events will not be removed from the persistent store; if the site is loaded again,
6054+
// the events will be flushed again on startup and deduplicated on the Mixpanel server
6055+
// side.
6056+
// There is no reliable way to capture only page close events, so we lean on the
6057+
// visibilitychange and pagehide events as recommended at
6058+
// https://developer.mozilla.org/en-US/docs/Web/API/Window/unload_event#usage_notes.
6059+
// These events fire when the user clicks away from the current page/tab, so will occur
6060+
// more frequently than page unload, but are the only mechanism currently for capturing
6061+
// this scenario somewhat reliably.
6062+
var flush_on_unload = _.bind(function() {
60886063
if (!this.request_batchers.events.stopped) {
60896064
this.request_batchers.events.flush({unloading: true});
60906065
}
6091-
}, this));
6066+
}, this);
6067+
window$1.addEventListener('pagehide', function(ev) {
6068+
if (ev['persisted']) {
6069+
flush_on_unload();
6070+
}
6071+
});
6072+
window$1.addEventListener('visibilitychange', function() {
6073+
if (document$1['visibilityState'] === 'hidden') {
6074+
flush_on_unload();
6075+
}
6076+
});
60926077
}
60936078
}
60946079
}

0 commit comments

Comments
 (0)