@mparticle/web-sdk 2.19.1 → 2.19.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/mparticle.common.js +13 -13
- package/dist/mparticle.esm.js +13 -13
- package/dist/mparticle.js +114 -85
- package/package.json +3 -2
- package/src/batchUploader.ts +77 -77
- package/src/forwarders.js +40 -20
- package/src/helpers.js +5 -0
- package/src/identity.js +10 -6
- package/src/vault.ts +21 -74
package/dist/mparticle.js
CHANGED
|
@@ -725,7 +725,7 @@ var mParticle = (function () {
|
|
|
725
725
|
Environment: Environment
|
|
726
726
|
};
|
|
727
727
|
|
|
728
|
-
var version = "2.19.
|
|
728
|
+
var version = "2.19.3";
|
|
729
729
|
|
|
730
730
|
var Constants = {
|
|
731
731
|
sdkVersion: version,
|
|
@@ -2304,132 +2304,144 @@ var mParticle = (function () {
|
|
|
2304
2304
|
|
|
2305
2305
|
BatchUploader.prototype.prepareAndUpload = function (triggerFuture, useBeacon) {
|
|
2306
2306
|
return __awaiter(this, void 0, void 0, function () {
|
|
2307
|
-
var currentUser, currentEvents, newBatches, batchesToUpload, batchesThatDidNotUpload
|
|
2307
|
+
var currentUser, currentEvents, newBatches, batchesToUpload, batchesThatDidNotUpload;
|
|
2308
2308
|
|
|
2309
|
-
var _a;
|
|
2310
|
-
|
|
2311
|
-
var _this_1 = this;
|
|
2312
|
-
|
|
2313
|
-
return __generator(this, function (_b) {
|
|
2314
|
-
currentUser = this.mpInstance.Identity.getCurrentUser();
|
|
2315
|
-
currentEvents = this.eventsQueuedForProcessing;
|
|
2316
|
-
this.eventsQueuedForProcessing = [];
|
|
2317
|
-
newBatches = BatchUploader.createNewBatches(currentEvents, currentUser, this.mpInstance);
|
|
2309
|
+
var _a, _b;
|
|
2318
2310
|
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2311
|
+
return __generator(this, function (_c) {
|
|
2312
|
+
switch (_c.label) {
|
|
2313
|
+
case 0:
|
|
2314
|
+
currentUser = this.mpInstance.Identity.getCurrentUser();
|
|
2315
|
+
currentEvents = this.eventsQueuedForProcessing;
|
|
2316
|
+
this.eventsQueuedForProcessing = [];
|
|
2317
|
+
newBatches = BatchUploader.createNewBatches(currentEvents, currentUser, this.mpInstance);
|
|
2322
2318
|
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
promises = batchesToUpload.map(function (upload) {
|
|
2327
|
-
return _this_1.upload(_this_1.mpInstance.Logger, upload, useBeacon);
|
|
2328
|
-
}); // Iterate through fulfilled promises and store any remaining batches
|
|
2329
|
-
// for future re-transmission attempts
|
|
2319
|
+
if (!isEmpty(newBatches)) {
|
|
2320
|
+
(_a = this.batchesQueuedForProcessing).push.apply(_a, newBatches);
|
|
2321
|
+
}
|
|
2330
2322
|
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
})["catch"](function (error) {
|
|
2337
|
-
_this_1.mpInstance.Logger.error("Error processing batches during upload attempt: ".concat(error));
|
|
2338
|
-
})["finally"](function () {
|
|
2339
|
-
var _a; // Any batches that did not upload should be put back into the queue for processing
|
|
2323
|
+
batchesToUpload = this.batchesQueuedForProcessing;
|
|
2324
|
+
this.batchesQueuedForProcessing = [];
|
|
2325
|
+
return [4
|
|
2326
|
+
/*yield*/
|
|
2327
|
+
, this.uploadBatches(this.mpInstance.Logger, batchesToUpload, useBeacon)];
|
|
2340
2328
|
|
|
2329
|
+
case 1:
|
|
2330
|
+
batchesThatDidNotUpload = _c.sent(); // Batches that do not successfully upload are added back to the process queue
|
|
2331
|
+
// in the order they were created so that we can attempt re-transmission in
|
|
2332
|
+
// the same sequence. This is to prevent any potential data corruption.
|
|
2341
2333
|
|
|
2342
2334
|
if (!isEmpty(batchesThatDidNotUpload)) {
|
|
2343
|
-
|
|
2335
|
+
// TODO: https://go.mparticle.com/work/SQDSDKS-5165
|
|
2336
|
+
(_b = this.batchesQueuedForProcessing).unshift.apply(_b, batchesThatDidNotUpload);
|
|
2344
2337
|
}
|
|
2345
|
-
});
|
|
2346
|
-
}
|
|
2347
2338
|
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2339
|
+
if (triggerFuture) {
|
|
2340
|
+
this.triggerUploadInterval(triggerFuture, false);
|
|
2341
|
+
}
|
|
2351
2342
|
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2343
|
+
return [2
|
|
2344
|
+
/*return*/
|
|
2345
|
+
];
|
|
2346
|
+
}
|
|
2355
2347
|
});
|
|
2356
2348
|
});
|
|
2357
|
-
};
|
|
2349
|
+
}; // TODO: Refactor to use logger as a class method
|
|
2350
|
+
// https://go.mparticle.com/work/SQDSDKS-5167
|
|
2351
|
+
|
|
2358
2352
|
|
|
2359
|
-
BatchUploader.prototype.
|
|
2353
|
+
BatchUploader.prototype.uploadBatches = function (logger, batches, useBeacon) {
|
|
2360
2354
|
return __awaiter(this, void 0, void 0, function () {
|
|
2361
|
-
var fetchPayload, blob, response,
|
|
2355
|
+
var uploads, i, fetchPayload, blob, response, e_1;
|
|
2362
2356
|
return __generator(this, function (_a) {
|
|
2363
2357
|
switch (_a.label) {
|
|
2364
2358
|
case 0:
|
|
2365
|
-
|
|
2359
|
+
uploads = batches.filter(function (batch) {
|
|
2360
|
+
return !isEmpty(batch.events);
|
|
2361
|
+
});
|
|
2362
|
+
|
|
2363
|
+
if (isEmpty(uploads)) {
|
|
2366
2364
|
return [2
|
|
2367
2365
|
/*return*/
|
|
2368
2366
|
, null];
|
|
2369
2367
|
}
|
|
2370
2368
|
|
|
2371
|
-
logger.verbose("Uploading batches: ".concat(JSON.stringify(
|
|
2369
|
+
logger.verbose("Uploading batches: ".concat(JSON.stringify(uploads)));
|
|
2370
|
+
logger.verbose("Batch count: ".concat(uploads.length));
|
|
2371
|
+
i = 0;
|
|
2372
|
+
_a.label = 1;
|
|
2373
|
+
|
|
2374
|
+
case 1:
|
|
2375
|
+
if (!(i < uploads.length)) return [3
|
|
2376
|
+
/*break*/
|
|
2377
|
+
, 6];
|
|
2372
2378
|
fetchPayload = {
|
|
2373
2379
|
method: 'POST',
|
|
2374
2380
|
headers: {
|
|
2375
2381
|
Accept: BatchUploader.CONTENT_TYPE,
|
|
2376
2382
|
'Content-Type': 'text/plain;charset=UTF-8'
|
|
2377
2383
|
},
|
|
2378
|
-
body: JSON.stringify(
|
|
2384
|
+
body: JSON.stringify(uploads[i])
|
|
2379
2385
|
};
|
|
2380
2386
|
if (!(useBeacon && this.isBeaconAvailable())) return [3
|
|
2381
2387
|
/*break*/
|
|
2382
|
-
,
|
|
2388
|
+
, 2];
|
|
2383
2389
|
blob = new Blob([fetchPayload.body], {
|
|
2384
2390
|
type: 'text/plain;charset=UTF-8'
|
|
2385
2391
|
});
|
|
2386
2392
|
navigator.sendBeacon(this.uploadUrl, blob);
|
|
2387
2393
|
return [3
|
|
2388
2394
|
/*break*/
|
|
2389
|
-
,
|
|
2395
|
+
, 5];
|
|
2390
2396
|
|
|
2391
|
-
case
|
|
2392
|
-
_a.trys.push([
|
|
2397
|
+
case 2:
|
|
2398
|
+
_a.trys.push([2, 4,, 5]);
|
|
2393
2399
|
|
|
2394
2400
|
return [4
|
|
2395
2401
|
/*yield*/
|
|
2396
2402
|
, this.uploader.upload(fetchPayload)];
|
|
2397
2403
|
|
|
2398
|
-
case
|
|
2399
|
-
response = _a.sent();
|
|
2404
|
+
case 3:
|
|
2405
|
+
response = _a.sent();
|
|
2400
2406
|
|
|
2401
2407
|
if (response.status >= 200 && response.status < 300) {
|
|
2402
|
-
logger.verbose("Upload success for request ID: ".concat(
|
|
2403
|
-
return [2
|
|
2404
|
-
/*return*/
|
|
2405
|
-
, null];
|
|
2408
|
+
logger.verbose("Upload success for request ID: ".concat(uploads[i].source_request_id));
|
|
2406
2409
|
} else if (response.status >= 500 || response.status === 429) {
|
|
2407
|
-
logger.error("HTTP error status ".concat(response.status, " received")); // Server error,
|
|
2410
|
+
logger.error("HTTP error status ".concat(response.status, " received")); // Server error, add back current batches and try again later
|
|
2408
2411
|
|
|
2409
2412
|
return [2
|
|
2410
2413
|
/*return*/
|
|
2411
|
-
,
|
|
2414
|
+
, uploads.slice(i, uploads.length)];
|
|
2412
2415
|
} else if (response.status >= 401) {
|
|
2413
|
-
logger.error("HTTP error status ".concat(response.status, " while uploading - please verify your API key.")); //
|
|
2414
|
-
// so return the upload so it can be stored for later use
|
|
2416
|
+
logger.error("HTTP error status ".concat(response.status, " while uploading - please verify your API key.")); //if we're getting a 401, assume we'll keep getting a 401 and clear the uploads.
|
|
2415
2417
|
|
|
2416
2418
|
return [2
|
|
2417
2419
|
/*return*/
|
|
2418
|
-
,
|
|
2420
|
+
, null];
|
|
2421
|
+
} else {
|
|
2422
|
+
// In case there is an HTTP error we did not anticipate.
|
|
2423
|
+
console.error("HTTP error status ".concat(response.status, " while uploading events."), response);
|
|
2424
|
+
throw new Error("Uncaught HTTP Error ".concat(response.status, ". Batch upload will be re-attempted."));
|
|
2419
2425
|
}
|
|
2420
2426
|
|
|
2421
2427
|
return [3
|
|
2422
2428
|
/*break*/
|
|
2423
|
-
,
|
|
2429
|
+
, 5];
|
|
2424
2430
|
|
|
2425
|
-
case
|
|
2426
|
-
|
|
2427
|
-
logger.error("Error sending event to mParticle servers. ".concat(
|
|
2431
|
+
case 4:
|
|
2432
|
+
e_1 = _a.sent();
|
|
2433
|
+
logger.error("Error sending event to mParticle servers. ".concat(e_1));
|
|
2428
2434
|
return [2
|
|
2429
2435
|
/*return*/
|
|
2430
|
-
,
|
|
2436
|
+
, uploads.slice(i, uploads.length)];
|
|
2431
2437
|
|
|
2432
|
-
case
|
|
2438
|
+
case 5:
|
|
2439
|
+
i++;
|
|
2440
|
+
return [3
|
|
2441
|
+
/*break*/
|
|
2442
|
+
, 1];
|
|
2443
|
+
|
|
2444
|
+
case 6:
|
|
2433
2445
|
return [2
|
|
2434
2446
|
/*return*/
|
|
2435
2447
|
, null];
|
|
@@ -3193,6 +3205,11 @@ var mParticle = (function () {
|
|
|
3193
3205
|
return filteredUserAttributes;
|
|
3194
3206
|
};
|
|
3195
3207
|
|
|
3208
|
+
this.isFilteredUserAttribute = function (userAttributeKey, filterList) {
|
|
3209
|
+
var hashedUserAttribute = self.generateHash(userAttributeKey);
|
|
3210
|
+
return filterList && self.inArray(filterList, hashedUserAttribute);
|
|
3211
|
+
};
|
|
3212
|
+
|
|
3196
3213
|
this.isEventType = function (type) {
|
|
3197
3214
|
for (var prop in Types.EventType) {
|
|
3198
3215
|
if (Types.EventType.hasOwnProperty(prop)) {
|
|
@@ -6171,6 +6188,10 @@ var mParticle = (function () {
|
|
|
6171
6188
|
|
|
6172
6189
|
function Forwarders(mpInstance, kitBlocker) {
|
|
6173
6190
|
var self = this;
|
|
6191
|
+
var UserAttributeActionTypes = {
|
|
6192
|
+
setUserAttribute: 'setUserAttribute',
|
|
6193
|
+
removeUserAttribute: 'removeUserAttribute'
|
|
6194
|
+
};
|
|
6174
6195
|
|
|
6175
6196
|
this.initForwarders = function (userIdentities, forwardingStatsCallback) {
|
|
6176
6197
|
var user = mpInstance.Identity.getCurrentUser();
|
|
@@ -6405,26 +6426,34 @@ var mParticle = (function () {
|
|
|
6405
6426
|
}
|
|
6406
6427
|
};
|
|
6407
6428
|
|
|
6408
|
-
this.
|
|
6409
|
-
if (kitBlocker && kitBlocker.isAttributeKeyBlocked(key)) {
|
|
6429
|
+
this.handleForwarderUserAttributes = function (functionNameKey, key, value) {
|
|
6430
|
+
if (kitBlocker && kitBlocker.isAttributeKeyBlocked(key) || !mpInstance._Store.activeForwarders.length) {
|
|
6410
6431
|
return;
|
|
6411
6432
|
}
|
|
6412
6433
|
|
|
6413
|
-
|
|
6414
|
-
|
|
6415
|
-
if (forwarder.setUserAttribute && forwarder.userAttributeFilters && !mpInstance._Helpers.inArray(forwarder.userAttributeFilters, mpInstance._Helpers.generateHash(key))) {
|
|
6416
|
-
try {
|
|
6417
|
-
var result = forwarder.setUserAttribute(key, value);
|
|
6434
|
+
mpInstance._Store.activeForwarders.forEach(function (forwarder) {
|
|
6435
|
+
var forwarderFunction = forwarder[functionNameKey];
|
|
6418
6436
|
|
|
6419
|
-
|
|
6420
|
-
|
|
6421
|
-
|
|
6422
|
-
|
|
6423
|
-
|
|
6424
|
-
|
|
6437
|
+
if (!forwarderFunction || mpInstance._Helpers.isFilteredUserAttribute(key, forwarder.userAttributeFilters)) {
|
|
6438
|
+
return;
|
|
6439
|
+
}
|
|
6440
|
+
|
|
6441
|
+
try {
|
|
6442
|
+
var result;
|
|
6443
|
+
|
|
6444
|
+
if (functionNameKey === UserAttributeActionTypes.setUserAttribute) {
|
|
6445
|
+
result = forwarder.setUserAttribute(key, value);
|
|
6446
|
+
} else if (functionNameKey === UserAttributeActionTypes.removeUserAttribute) {
|
|
6447
|
+
result = forwarder.removeUserAttribute(key);
|
|
6425
6448
|
}
|
|
6426
|
-
|
|
6427
|
-
|
|
6449
|
+
|
|
6450
|
+
if (result) {
|
|
6451
|
+
mpInstance.Logger.verbose(result);
|
|
6452
|
+
}
|
|
6453
|
+
} catch (e) {
|
|
6454
|
+
mpInstance.Logger.error(e);
|
|
6455
|
+
}
|
|
6456
|
+
});
|
|
6428
6457
|
};
|
|
6429
6458
|
|
|
6430
6459
|
this.setForwarderUserIdentities = function (userIdentities) {
|
|
@@ -7629,7 +7658,7 @@ var mParticle = (function () {
|
|
|
7629
7658
|
|
|
7630
7659
|
mpInstance._Forwarders.initForwarders(self.IdentityAPI.getCurrentUser().getUserIdentities(), mpInstance._APIClient.prepareForwardingStats);
|
|
7631
7660
|
|
|
7632
|
-
mpInstance._Forwarders.
|
|
7661
|
+
mpInstance._Forwarders.handleForwarderUserAttributes('setUserAttribute', key, newValue);
|
|
7633
7662
|
}
|
|
7634
7663
|
}
|
|
7635
7664
|
},
|
|
@@ -7698,7 +7727,7 @@ var mParticle = (function () {
|
|
|
7698
7727
|
|
|
7699
7728
|
mpInstance._Forwarders.initForwarders(self.IdentityAPI.getCurrentUser().getUserIdentities(), mpInstance._APIClient.prepareForwardingStats);
|
|
7700
7729
|
|
|
7701
|
-
mpInstance._Forwarders.
|
|
7730
|
+
mpInstance._Forwarders.handleForwarderUserAttributes('removeUserAttribute', key, null);
|
|
7702
7731
|
}
|
|
7703
7732
|
},
|
|
7704
7733
|
|
|
@@ -7776,7 +7805,7 @@ var mParticle = (function () {
|
|
|
7776
7805
|
|
|
7777
7806
|
mpInstance._Forwarders.initForwarders(self.IdentityAPI.getCurrentUser().getUserIdentities(), mpInstance._APIClient.prepareForwardingStats);
|
|
7778
7807
|
|
|
7779
|
-
mpInstance._Forwarders.
|
|
7808
|
+
mpInstance._Forwarders.handleForwarderUserAttributes('setUserAttribute', key, arrayCopy);
|
|
7780
7809
|
}
|
|
7781
7810
|
},
|
|
7782
7811
|
|
|
@@ -7799,7 +7828,7 @@ var mParticle = (function () {
|
|
|
7799
7828
|
if (userAttributes) {
|
|
7800
7829
|
for (var prop in userAttributes) {
|
|
7801
7830
|
if (userAttributes.hasOwnProperty(prop)) {
|
|
7802
|
-
mpInstance._Forwarders.
|
|
7831
|
+
mpInstance._Forwarders.handleForwarderUserAttributes('removeUserAttribute', prop, null);
|
|
7803
7832
|
}
|
|
7804
7833
|
|
|
7805
7834
|
this.removeUserAttribute(prop);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mparticle/web-sdk",
|
|
3
|
-
"version": "2.19.
|
|
3
|
+
"version": "2.19.3",
|
|
4
4
|
"description": "mParticle core SDK for web applications",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"keywords": [
|
|
@@ -28,13 +28,14 @@
|
|
|
28
28
|
"build:esm": "cross-env ENVIRONMENT=prod BUILD=esm rollup --config rollup.config.js",
|
|
29
29
|
"build:stub": "cross-env ENVIRONMENT=prod BUILD=stub rollup --config rollup.config.js",
|
|
30
30
|
"build:snippet": "uglifyjs snippet.js -nm -o snippet.min.js",
|
|
31
|
+
"build:test-bundle": "cross-env TESTTYPE=main ENVIRONMENT=prod rollup --config rollup.test.config.js",
|
|
31
32
|
"build:browserify:cjs": "browserify test/integrations/cjs/browserify/index.js -o test/integrations/cjs/dist/browserify-output.js && npm run test:karma:browserify:cjs",
|
|
32
33
|
"build:rollup:cjs": "rollup --config test/integrations/cjs/rollup/rollup.config.js && npm run test:karma:rollup:cjs",
|
|
33
34
|
"build:webpack:cjs": "webpack --config test/integrations/cjs/webpack/webpack.config.js && npm run test:karma:webpack:cjs",
|
|
34
35
|
"build:rollup:module": "rollup --config test/integrations/module/rollup/rollup.config.js && npm run test:karma:rollup:module",
|
|
35
36
|
"build:webpack:module": "webpack --config test/integrations/module/webpack/webpack.config.js && npm run test:karma:webpack:module",
|
|
36
37
|
"build:ts": "tsc -p .",
|
|
37
|
-
"test": "npm run build &&
|
|
38
|
+
"test": "npm run build && npm run build:test-bundle && cross-env DEBUG=false karma start test/karma.config.js",
|
|
38
39
|
"test:debug": "cross-env DEBUG=true karma start test/karma.config.js",
|
|
39
40
|
"test:stub": "cross-env TESTTYPE=stub ENVIRONMENT=prod rollup --config rollup.test.config.js && karma start test/stub/karma.stub.config.js",
|
|
40
41
|
"test:integrations": "npm run test:requirejs && npm run test:integrations:cjs && npm run test:integrations:module",
|
package/src/batchUploader.ts
CHANGED
|
@@ -211,6 +211,7 @@ export class BatchUploader {
|
|
|
211
211
|
triggerFuture: boolean,
|
|
212
212
|
useBeacon: boolean
|
|
213
213
|
): Promise<void> {
|
|
214
|
+
// Fetch current user so that events can be grouped by MPID
|
|
214
215
|
const currentUser = this.mpInstance.Identity.getCurrentUser();
|
|
215
216
|
|
|
216
217
|
const currentEvents = this.eventsQueuedForProcessing;
|
|
@@ -221,43 +222,27 @@ export class BatchUploader {
|
|
|
221
222
|
currentUser,
|
|
222
223
|
this.mpInstance
|
|
223
224
|
);
|
|
225
|
+
|
|
224
226
|
if (!isEmpty(newBatches)) {
|
|
225
227
|
this.batchesQueuedForProcessing.push(...newBatches);
|
|
226
228
|
}
|
|
227
229
|
|
|
230
|
+
// Clear out pending batches to avoid any potential duplication
|
|
228
231
|
const batchesToUpload = this.batchesQueuedForProcessing;
|
|
229
|
-
const batchesThatDidNotUpload: Batch[] = [];
|
|
230
232
|
this.batchesQueuedForProcessing = [];
|
|
231
233
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
234
|
+
const batchesThatDidNotUpload = await this.uploadBatches(
|
|
235
|
+
this.mpInstance.Logger,
|
|
236
|
+
batchesToUpload,
|
|
237
|
+
useBeacon
|
|
238
|
+
);
|
|
236
239
|
|
|
237
|
-
//
|
|
238
|
-
//
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
!isEmpty(batch)
|
|
244
|
-
? batchesThatDidNotUpload.push(batch)
|
|
245
|
-
: null
|
|
246
|
-
);
|
|
247
|
-
})
|
|
248
|
-
.catch((error) => {
|
|
249
|
-
this.mpInstance.Logger.error(
|
|
250
|
-
`Error processing batches during upload attempt: ${error}`
|
|
251
|
-
);
|
|
252
|
-
})
|
|
253
|
-
.finally(() => {
|
|
254
|
-
// Any batches that did not upload should be put back into the queue for processing
|
|
255
|
-
if (!isEmpty(batchesThatDidNotUpload)) {
|
|
256
|
-
this.batchesQueuedForProcessing.unshift(
|
|
257
|
-
...batchesThatDidNotUpload
|
|
258
|
-
);
|
|
259
|
-
}
|
|
260
|
-
});
|
|
240
|
+
// Batches that do not successfully upload are added back to the process queue
|
|
241
|
+
// in the order they were created so that we can attempt re-transmission in
|
|
242
|
+
// the same sequence. This is to prevent any potential data corruption.
|
|
243
|
+
if (!isEmpty(batchesThatDidNotUpload)) {
|
|
244
|
+
// TODO: https://go.mparticle.com/work/SQDSDKS-5165
|
|
245
|
+
this.batchesQueuedForProcessing.unshift(...batchesThatDidNotUpload);
|
|
261
246
|
}
|
|
262
247
|
|
|
263
248
|
if (triggerFuture) {
|
|
@@ -265,64 +250,79 @@ export class BatchUploader {
|
|
|
265
250
|
}
|
|
266
251
|
}
|
|
267
252
|
|
|
268
|
-
|
|
253
|
+
// TODO: Refactor to use logger as a class method
|
|
254
|
+
// https://go.mparticle.com/work/SQDSDKS-5167
|
|
255
|
+
private async uploadBatches(
|
|
269
256
|
logger: SDKLoggerApi,
|
|
270
|
-
|
|
257
|
+
batches: Batch[],
|
|
271
258
|
useBeacon: boolean
|
|
272
|
-
): Promise<Batch | null> {
|
|
273
|
-
|
|
259
|
+
): Promise<Batch[] | null> {
|
|
260
|
+
// Filter out any batches that don't have events
|
|
261
|
+
const uploads = batches.filter((batch) => !isEmpty(batch.events));
|
|
262
|
+
|
|
263
|
+
if (isEmpty(uploads)) {
|
|
274
264
|
return null;
|
|
275
265
|
}
|
|
276
266
|
|
|
277
|
-
logger.verbose(`Uploading batches: ${JSON.stringify(
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
// beacon is only used on onbeforeunload onpagehide events
|
|
290
|
-
if (useBeacon && this.isBeaconAvailable()) {
|
|
291
|
-
let blob = new Blob([fetchPayload.body], {
|
|
292
|
-
type: 'text/plain;charset=UTF-8',
|
|
293
|
-
});
|
|
294
|
-
navigator.sendBeacon(this.uploadUrl, blob);
|
|
295
|
-
} else {
|
|
296
|
-
try {
|
|
297
|
-
const response = await this.uploader.upload(fetchPayload);
|
|
298
|
-
|
|
299
|
-
// TODO: Should we make this a switch statement instead?
|
|
300
|
-
if (response.status >= 200 && response.status < 300) {
|
|
301
|
-
logger.verbose(
|
|
302
|
-
`Upload success for request ID: ${batch.source_request_id}`
|
|
303
|
-
);
|
|
267
|
+
logger.verbose(`Uploading batches: ${JSON.stringify(uploads)}`);
|
|
268
|
+
logger.verbose(`Batch count: ${uploads.length}`);
|
|
269
|
+
|
|
270
|
+
for (let i = 0; i < uploads.length; i++) {
|
|
271
|
+
const fetchPayload: fetchPayload = {
|
|
272
|
+
method: 'POST',
|
|
273
|
+
headers: {
|
|
274
|
+
Accept: BatchUploader.CONTENT_TYPE,
|
|
275
|
+
'Content-Type': 'text/plain;charset=UTF-8',
|
|
276
|
+
},
|
|
277
|
+
body: JSON.stringify(uploads[i]),
|
|
278
|
+
};
|
|
304
279
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
280
|
+
// beacon is only used on onbeforeunload onpagehide events
|
|
281
|
+
if (useBeacon && this.isBeaconAvailable()) {
|
|
282
|
+
let blob = new Blob([fetchPayload.body], {
|
|
283
|
+
type: 'text/plain;charset=UTF-8',
|
|
284
|
+
});
|
|
285
|
+
navigator.sendBeacon(this.uploadUrl, blob);
|
|
286
|
+
} else {
|
|
287
|
+
try {
|
|
288
|
+
const response = await this.uploader.upload(fetchPayload);
|
|
289
|
+
|
|
290
|
+
if (response.status >= 200 && response.status < 300) {
|
|
291
|
+
logger.verbose(
|
|
292
|
+
`Upload success for request ID: ${uploads[i].source_request_id}`
|
|
293
|
+
);
|
|
294
|
+
} else if (
|
|
295
|
+
response.status >= 500 ||
|
|
296
|
+
response.status === 429
|
|
297
|
+
) {
|
|
298
|
+
logger.error(
|
|
299
|
+
`HTTP error status ${response.status} received`
|
|
300
|
+
);
|
|
301
|
+
// Server error, add back current batches and try again later
|
|
302
|
+
return uploads.slice(i, uploads.length);
|
|
303
|
+
} else if (response.status >= 401) {
|
|
304
|
+
logger.error(
|
|
305
|
+
`HTTP error status ${response.status} while uploading - please verify your API key.`
|
|
306
|
+
);
|
|
307
|
+
//if we're getting a 401, assume we'll keep getting a 401 and clear the uploads.
|
|
308
|
+
return null;
|
|
309
|
+
} else {
|
|
310
|
+
// In case there is an HTTP error we did not anticipate.
|
|
311
|
+
console.error(
|
|
312
|
+
`HTTP error status ${response.status} while uploading events.`,
|
|
313
|
+
response
|
|
314
|
+
);
|
|
310
315
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
316
|
+
throw new Error(
|
|
317
|
+
`Uncaught HTTP Error ${response.status}. Batch upload will be re-attempted.`
|
|
318
|
+
);
|
|
319
|
+
}
|
|
320
|
+
} catch (e) {
|
|
314
321
|
logger.error(
|
|
315
|
-
`
|
|
322
|
+
`Error sending event to mParticle servers. ${e}`
|
|
316
323
|
);
|
|
317
|
-
|
|
318
|
-
// so return the upload so it can be stored for later use
|
|
319
|
-
return batch;
|
|
324
|
+
return uploads.slice(i, uploads.length);
|
|
320
325
|
}
|
|
321
|
-
} catch (error) {
|
|
322
|
-
logger.error(
|
|
323
|
-
`Error sending event to mParticle servers. ${error}`
|
|
324
|
-
);
|
|
325
|
-
return batch;
|
|
326
326
|
}
|
|
327
327
|
}
|
|
328
328
|
return null;
|
package/src/forwarders.js
CHANGED
|
@@ -3,6 +3,12 @@ import filteredMparticleUser from './filteredMparticleUser';
|
|
|
3
3
|
|
|
4
4
|
export default function Forwarders(mpInstance, kitBlocker) {
|
|
5
5
|
var self = this;
|
|
6
|
+
|
|
7
|
+
const UserAttributeActionTypes = {
|
|
8
|
+
setUserAttribute: 'setUserAttribute',
|
|
9
|
+
removeUserAttribute: 'removeUserAttribute',
|
|
10
|
+
};
|
|
11
|
+
|
|
6
12
|
this.initForwarders = function(userIdentities, forwardingStatsCallback) {
|
|
7
13
|
var user = mpInstance.Identity.getCurrentUser();
|
|
8
14
|
if (
|
|
@@ -387,33 +393,47 @@ export default function Forwarders(mpInstance, kitBlocker) {
|
|
|
387
393
|
}
|
|
388
394
|
};
|
|
389
395
|
|
|
390
|
-
this.
|
|
391
|
-
if (
|
|
396
|
+
this.handleForwarderUserAttributes = function(functionNameKey, key, value) {
|
|
397
|
+
if (
|
|
398
|
+
(kitBlocker && kitBlocker.isAttributeKeyBlocked(key)) ||
|
|
399
|
+
!mpInstance._Store.activeForwarders.length
|
|
400
|
+
) {
|
|
392
401
|
return;
|
|
393
402
|
}
|
|
394
403
|
|
|
395
|
-
|
|
396
|
-
|
|
404
|
+
mpInstance._Store.activeForwarders.forEach(function(forwarder) {
|
|
405
|
+
const forwarderFunction = forwarder[functionNameKey];
|
|
406
|
+
if (
|
|
407
|
+
!forwarderFunction ||
|
|
408
|
+
mpInstance._Helpers.isFilteredUserAttribute(
|
|
409
|
+
key,
|
|
410
|
+
forwarder.userAttributeFilters
|
|
411
|
+
)
|
|
412
|
+
) {
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
415
|
+
try {
|
|
416
|
+
let result;
|
|
417
|
+
|
|
397
418
|
if (
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
!mpInstance._Helpers.inArray(
|
|
401
|
-
forwarder.userAttributeFilters,
|
|
402
|
-
mpInstance._Helpers.generateHash(key)
|
|
403
|
-
)
|
|
419
|
+
functionNameKey ===
|
|
420
|
+
UserAttributeActionTypes.setUserAttribute
|
|
404
421
|
) {
|
|
405
|
-
|
|
406
|
-
|
|
422
|
+
result = forwarder.setUserAttribute(key, value);
|
|
423
|
+
} else if (
|
|
424
|
+
functionNameKey ===
|
|
425
|
+
UserAttributeActionTypes.removeUserAttribute
|
|
426
|
+
) {
|
|
427
|
+
result = forwarder.removeUserAttribute(key);
|
|
428
|
+
}
|
|
407
429
|
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
}
|
|
411
|
-
} catch (e) {
|
|
412
|
-
mpInstance.Logger.error(e);
|
|
413
|
-
}
|
|
430
|
+
if (result) {
|
|
431
|
+
mpInstance.Logger.verbose(result);
|
|
414
432
|
}
|
|
415
|
-
})
|
|
416
|
-
|
|
433
|
+
} catch (e) {
|
|
434
|
+
mpInstance.Logger.error(e);
|
|
435
|
+
}
|
|
436
|
+
});
|
|
417
437
|
};
|
|
418
438
|
|
|
419
439
|
this.setForwarderUserIdentities = function(userIdentities) {
|
package/src/helpers.js
CHANGED
|
@@ -387,6 +387,11 @@ export default function Helpers(mpInstance) {
|
|
|
387
387
|
return filteredUserAttributes;
|
|
388
388
|
};
|
|
389
389
|
|
|
390
|
+
this.isFilteredUserAttribute = function(userAttributeKey, filterList) {
|
|
391
|
+
const hashedUserAttribute = self.generateHash(userAttributeKey);
|
|
392
|
+
return filterList && self.inArray(filterList, hashedUserAttribute);
|
|
393
|
+
};
|
|
394
|
+
|
|
390
395
|
this.isEventType = function(type) {
|
|
391
396
|
for (var prop in Types.EventType) {
|
|
392
397
|
if (Types.EventType.hasOwnProperty(prop)) {
|