Skip to content

Commit

Permalink
refactor: Use fetch instead of XHR for forwarding stats uploads (#904)
Browse files Browse the repository at this point in the history
  • Loading branch information
rmi22186 committed Sep 4, 2024
1 parent 7adb20b commit 59819c9
Show file tree
Hide file tree
Showing 10 changed files with 97 additions and 45 deletions.
85 changes: 43 additions & 42 deletions src/apiClient.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import Constants from './constants';
import Types from './types';
import { BatchUploader } from './batchUploader';
import { MParticleWebSDK, SDKEvent } from './sdkRuntimeModels';
import { MParticleWebSDK, SDKEvent, SDKDataPlan } from './sdkRuntimeModels';
import KitBlocker from './kitBlocking';
import { Dictionary, getRampNumber, isEmpty, parseNumber } from './utils';
import { IUploadObject } from './serverModel';
import { MPForwarder } from './forwarders.interfaces';
import { IMParticleUser } from './identity-user-interfaces';

export type ForwardingStatsData = Dictionary<any>;
import { IMParticleUser, ISDKUserAttributes } from './identity-user-interfaces';
import { AsyncUploader, FetchUploader, XHRUploader } from './uploaders';

export interface IAPIClient {
uploader: BatchUploader | null;
Expand All @@ -18,18 +17,30 @@ export interface IAPIClient {
sendEventToServer: (event: SDKEvent, _options?: Dictionary<any>) => void;
sendSingleEventToServer: (event: SDKEvent) => void;
sendBatchForwardingStatsToServer: (
forwardingStatsData: ForwardingStatsData,
forwardingStatsData: IForwardingStatsData,
xhr: XMLHttpRequest
) => void;
sendSingleForwardingStatsToServer: (
forwardingStatsData: ForwardingStatsData
) => void;
initializeForwarderStatsUploader: () => AsyncUploader;
prepareForwardingStats: (
forwarder: MPForwarder,
event: IUploadObject
) => void;
}

export interface IForwardingStatsData {
mid: number; // Module Id
esid: number; // Event Subscription Id
n: string; // Event Name
attrs: ISDKUserAttributes; // User Attributes
sdk: string; // SDK Version
dt: number; // Data Type
et: number; // Event Type
dbg: boolean; // Development Mode (for debugging in Live Stream)
ct: number; // Current Timestamp
eec: number; // Expanded Event Count
dp: SDKDataPlan; // Data Plan
}

export default function APIClient(
this: IAPIClient,
mpInstance: MParticleWebSDK,
Expand Down Expand Up @@ -161,41 +172,26 @@ export default function APIClient(
}
};

this.sendSingleForwardingStatsToServer = function(forwardingStatsData) {
let url;
let data;
try {
const xhrCallback = function() {
if (xhr.readyState === 4) {
if (xhr.status === 202) {
mpInstance.Logger.verbose(
'Successfully sent ' +
xhr.statusText +
' from server'
);
}
}
};
const xhr = mpInstance._Helpers.createXHR(xhrCallback);
url = mpInstance._Helpers.createServiceUrl(
mpInstance._Store.SDKConfig.v1SecureServiceUrl,
mpInstance._Store.devToken
);
data = forwardingStatsData;
this.initializeForwarderStatsUploader = (): AsyncUploader => {
const {
v1SecureServiceUrl: forwardingDomain,
} = mpInstance._Store.SDKConfig;
const { devToken } = mpInstance._Store;

if (xhr) {
xhr.open('post', url + '/Forwarding');
xhr.send(JSON.stringify(data));
}
} catch (e) {
mpInstance.Logger.error(
'Error sending forwarding stats to mParticle servers.'
);
}
const uploadUrl: string = `https://${forwardingDomain}${devToken}/Forwarding`;

const uploader: AsyncUploader = window.fetch
? new FetchUploader(uploadUrl)
: new XHRUploader(uploadUrl);

return uploader;
};

this.prepareForwardingStats = function(forwarder, event) {
let forwardingStatsData;
this.prepareForwardingStats = function(
forwarder: MPForwarder,
event:SDKEvent,
) : void {
let forwardingStatsData: IForwardingStatsData;
const queue = mpInstance._Forwarders.getForwarderStatsQueue();

if (forwarder && forwarder.isVisible) {
Expand All @@ -212,16 +208,21 @@ export default function APIClient(
eec: event.ExpandedEventCount,
dp: event.DataPlan,
};

const {
sendSingleForwardingStatsToServer,
setForwarderStatsQueue,
} = mpInstance._Forwarders;

if (
mpInstance._Helpers.getFeatureFlag(
Constants.FeatureFlags.ReportBatching
)
) {
queue.push(forwardingStatsData);
mpInstance._Forwarders.setForwarderStatsQueue(queue);
setForwarderStatsQueue(queue);
} else {
self.sendSingleForwardingStatsToServer(forwardingStatsData);
sendSingleForwardingStatsToServer(forwardingStatsData);
}
}
};
Expand Down
32 changes: 32 additions & 0 deletions src/forwarders.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,16 @@ import filteredMparticleUser from './filteredMparticleUser';
import { isEmpty } from './utils';
import KitFilterHelper from './kitFilterHelper';
import Constants from './constants';
import APIClient from './apiClient';

const { Modify, Identify, Login, Logout } = Constants.IdentityMethods;

export default function Forwarders(mpInstance, kitBlocker) {
var self = this;
this.forwarderStatsUploader = new APIClient(
mpInstance,
kitBlocker
).initializeForwarderStatsUploader();

const UserAttributeActionTypes = {
setUserAttribute: 'setUserAttribute',
Expand Down Expand Up @@ -771,4 +776,31 @@ export default function Forwarders(mpInstance, kitBlocker) {
);
}
};

this.sendSingleForwardingStatsToServer = async forwardingStatsData => {
// https://go.mparticle.com/work/SQDSDKS-6568
const fetchPayload = {
method: 'post',
body: JSON.stringify(forwardingStatsData),
headers: {
Accept: 'text/plain;charset=UTF-8',
'Content-Type': 'text/plain;charset=UTF-8',
},
};

const response = await this.forwarderStatsUploader.upload(fetchPayload);

let message;
// This is a fire and forget, so we only need to log the response based on the code, and not return any response body
if (response.status === 202) {
// https://go.mparticle.com/work/SQDSDKS-6670
message = 'Successfully sent forwarding stats to mParticle Servers';
} else {
message =
'Issue with forwarding stats to mParticle Servers, received HTTP Code of ' +
response.statusText;
}

mpInstance?.Logger?.verbose(message);
};
}
4 changes: 2 additions & 2 deletions src/persistence.interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
Product,
UserIdentities,
} from '@mparticle/web-sdk';
import { ForwardingStatsData } from './apiClient';
import { IForwardingStatsData } from './apiClient';
import {
IntegrationAttributes,
ServerSettings,
Expand All @@ -18,7 +18,7 @@ import { UserAttributes } from './identity-user-interfaces';
export type UploadsTable = Dictionary<any>;
export interface iForwardingStatsBatches {
uploadsTable: UploadsTable;
forwardingStatsEventQueue: ForwardingStatsData[];
forwardingStatsEventQueue: IForwardingStatsData[];
}

export interface IGlobalStoreV2MinifiedKeys {
Expand Down
1 change: 1 addition & 0 deletions src/sdkRuntimeModels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ export interface SDKEvent {
CurrencyCode: string;
DataPlan?: SDKDataPlan;
LaunchReferral?: string;
ExpandedEventCount: number;
}
export interface SDKGeoLocation {
lat: number | string;
Expand Down
4 changes: 4 additions & 0 deletions test/fixtures/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export const event0: SDKEvent = {
SourceMessageId: 'test-smid',
EventDataType: 4,
EventCategory: 1,
ExpandedEventCount: 0,
CustomFlags: {},
IsFirstRun: false,
CurrencyCode: null,
Expand All @@ -27,6 +28,7 @@ export const event1: SDKEvent = {
SourceMessageId: 'test-smid',
EventDataType: 4,
EventCategory: 1,
ExpandedEventCount: 0,
CustomFlags: {},
IsFirstRun: false,
CurrencyCode: null,
Expand All @@ -48,6 +50,7 @@ export const event2: SDKEvent = {
SourceMessageId: 'test-smid',
EventDataType: 4,
EventCategory: 1,
ExpandedEventCount: 0,
CustomFlags: {},
IsFirstRun: false,
CurrencyCode: null,
Expand All @@ -69,6 +72,7 @@ export const event3: SDKEvent = {
SourceMessageId: 'test-smid',
EventDataType: 4,
EventCategory: 1,
ExpandedEventCount: 0,
CustomFlags: {},
IsFirstRun: false,
CurrencyCode: null,
Expand Down
3 changes: 3 additions & 0 deletions test/src/tests-batchUploader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ describe('batch uploader', () => {
SourceMessageId: 'test-smid',
EventDataType: 4,
EventCategory: 1,
ExpandedEventCount: 0,
CustomFlags: {},
IsFirstRun: false,
CurrencyCode: null,
Expand Down Expand Up @@ -384,6 +385,7 @@ describe('batch uploader', () => {
SourceMessageId: 'test-smid',
EventDataType: 4,
EventCategory: 1,
ExpandedEventCount: 0,
CustomFlags: {},
IsFirstRun: false,
CurrencyCode: null,
Expand Down Expand Up @@ -439,6 +441,7 @@ describe('batch uploader', () => {
SourceMessageId: 'test-smid',
EventDataType: 4,
EventCategory: 1,
ExpandedEventCount: 0,
CustomFlags: {},
IsFirstRun: false,
CurrencyCode: null,
Expand Down
7 changes: 6 additions & 1 deletion test/src/tests-forwarders.js
Original file line number Diff line number Diff line change
Expand Up @@ -993,6 +993,11 @@ describe('forwarders', function() {
});

it('sends events to forwarder v1 endpoint when mParticle.config.isDevelopmentMode = config.isDebug = false', function(done) {
fetchMock.post(urls.forwarding, {
status: 200,
body: JSON.stringify({ mpid: testMPID, is_logged_in: false }),
});

mParticle._resetForTests(MPConfig);
mParticle.config.isDevelopmentMode = false;
const mockForwarder = new MockForwarder();
Expand All @@ -1011,7 +1016,7 @@ describe('forwarders', function() {
true
);

mockServer.requests[mockServer.requests.length - 1].url.includes(
fetchMock.lastCall().includes(
'/v1/JS/test_key/Forwarding'
);

Expand Down
3 changes: 3 additions & 0 deletions test/src/tests-kit-blocking.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ describe('kit blocking', () => {
IsFirstRun: true,
EventName: null,
EventCategory: null,
ExpandedEventCount: 0,
MPID: testMPID,
EventAttributes: null,
SDKVersion: '1.0.0',
Expand Down Expand Up @@ -219,6 +220,7 @@ describe('kit blocking', () => {
IsFirstRun: true,
EventName: null,
EventCategory: null,
ExpandedEventCount: 0,
MPID: testMPID,
EventAttributes: null,
SDKVersion: '1.0.0',
Expand Down Expand Up @@ -430,6 +432,7 @@ describe('kit blocking', () => {
IsFirstRun: true,
EventName: null,
EventCategory: null,
ExpandedEventCount: 0,
MPID: testMPID,
EventAttributes: null,
SDKVersion: '1.0.0',
Expand Down
2 changes: 2 additions & 0 deletions test/src/tests-runtimeToBatchEventsDTO.ts
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,7 @@ describe('Old model to batch model conversion', () => {
const sdkEvent: SDKEvent = {
EventName: 'eCommerce - Purchase',
EventCategory: 16,
ExpandedEventCount: 0,
EventAttributes: null,
SDKVersion: '2.9.10',
SourceMessageId: 'testSMID',
Expand Down Expand Up @@ -420,6 +421,7 @@ describe('Old model to batch model conversion', () => {
const sdkEvent: SDKEvent = {
EventName: "Pause Event",
EventCategory: 9,
ExpandedEventCount: 0,
EventDataType: 4,
EventAttributes: {
content_duration: '120000',
Expand Down
1 change: 1 addition & 0 deletions test/src/tests-serverModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ describe('ServerModel', () => {
// or set up an event factory
const event: SDKEvent = {
EventName: 'Test Event',
ExpandedEventCount: 0,
MPID: '',
IsFirstRun: true,
DeviceId: 'test-device',
Expand Down

0 comments on commit 59819c9

Please sign in to comment.