Skip to content

fix: removes Inject plugins #837

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 0 additions & 25 deletions example/src/plugins/InjectTraits.ts

This file was deleted.

2 changes: 1 addition & 1 deletion packages/core/src/__tests__/methods/identify.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ describe('methods #identify', () => {
});
});

it('is concurrency safe', async () => {
it('adds userInfo to next events, concurrency safe', async () => {
// We trigger an identify and do not await it, we do a track immediately and await.
// The track call should have the correct values injected into it.
void client.identify('new-user-id');
Expand Down
109 changes: 94 additions & 15 deletions packages/core/src/analytics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {
import { settingsCDN, workspaceDestinationFilterKey } from './constants';
import { getContext } from './context';
import {
applyRawEventData,
createAliasEvent,
createGroupEvent,
createIdentifyEvent,
Expand All @@ -22,8 +21,6 @@ import {
} from './flushPolicies';
import { FlushPolicyExecuter } from './flushPolicies/flush-policy-executer';
import type { DestinationPlugin, PlatformPlugin, Plugin } from './plugin';
import { InjectContext } from './plugins/InjectContext';
import { InjectUserInfo } from './plugins/InjectUserInfo';
import { SegmentDestination } from './plugins/SegmentDestination';
import {
createGetter,
Expand All @@ -33,7 +30,7 @@ import {
Watchable,
} from './storage';
import { Timeline } from './timeline';
import type { DestinationFilters, SegmentAPISettings } from './types';
import { DestinationFilters, EventType, SegmentAPISettings } from './types';
import {
Config,
Context,
Expand Down Expand Up @@ -91,10 +88,7 @@ export class SegmentClient {

private onPluginAddedObservers: OnPluginAddedCallback[] = [];

private readonly platformPlugins: PlatformPlugin[] = [
new InjectUserInfo(),
new InjectContext(),
];
private readonly platformPlugins: PlatformPlugin[] = [];

// Watchables
/**
Expand Down Expand Up @@ -256,9 +250,12 @@ export class SegmentClient {
await this.storageReady();
}

// Get new settings from segment
// It's important to run this before checkInstalledVersion and trackDeeplinks to give time for destination plugins
// which make use of the settings object to initialize
await this.fetchSettings();

await allSettled([
// Get new settings from segment
this.fetchSettings(),
// save the current installed version
this.checkInstalledVersion(),
// check if the app was opened from a deep link
Expand Down Expand Up @@ -411,7 +408,8 @@ export class SegmentClient {
}

async process(incomingEvent: SegmentEvent) {
const event = applyRawEventData(incomingEvent);
const event = await this.applyRawEventData(incomingEvent);

if (this.isReady.value) {
this.flushPolicyExecuter.notify(event);
return this.timeline.process(event);
Expand Down Expand Up @@ -663,10 +661,8 @@ export class SegmentClient {

async reset(resetAnonymousId = true) {
try {
const anonymousId =
resetAnonymousId === true
? getUUID()
: this.store.userInfo.get().anonymousId;
const { anonymousId: currentId } = await this.store.userInfo.get(true);
const anonymousId = resetAnonymousId === true ? getUUID() : currentId;

await this.store.userInfo.set({
anonymousId,
Expand Down Expand Up @@ -766,4 +762,87 @@ export class SegmentClient {
}
this.config.errorHandler?.(error);
}

/**
* Injects context and userInfo data into the event, sets the messageId and timestamp
* This is handled outside of the timeline to prevent concurrency issues between plugins
* @param event Segment Event
* @returns event with data injected
*/
private applyRawEventData = async (
event: SegmentEvent
): Promise<SegmentEvent> => {
const userInfo = await this.processUserInfo(event);
const context = await this.context.get(true);

return {
...event,
...userInfo,
context: {
...event.context,
...context,
},
messageId: getUUID(),
timestamp: new Date().toISOString(),
integrations: event.integrations ?? {},
} as SegmentEvent;
};

/**
* Processes the userInfo to add to an event.
* For Identify and Alias: it saves the new userId and traits into the storage
* For all: set the userId and anonymousId from the current values
* @param event segment event
* @returns userInfo to inject to an event
*/
private processUserInfo = async (
event: SegmentEvent
): Promise<Partial<SegmentEvent>> => {
// Order here is IMPORTANT!
// Identify and Alias userInfo set operations have to come as soon as possible
// Do not block the set by doing a safe get first as it might cause a race condition
// within events procesing in the timeline asyncronously
if (event.type === EventType.IdentifyEvent) {
const userInfo = await this.userInfo.set((state) => ({
...state,
userId: event.userId ?? state.userId,
traits: {
...state.traits,
...event.traits,
},
}));

return {
anonymousId: userInfo.anonymousId,
userId: event.userId ?? userInfo.userId,
traits: {
...userInfo.traits,
...event.traits,
},
};
} else if (event.type === EventType.AliasEvent) {
let previousUserId: string;

const userInfo = await this.userInfo.set((state) => {
previousUserId = state.userId ?? state.anonymousId;

return {
...state,
userId: event.userId,
};
});

return {
anonymousId: userInfo.anonymousId,
userId: event.userId,
previousId: previousUserId!,
};
}

const userInfo = await this.userInfo.get(true);
return {
anonymousId: userInfo.anonymousId,
userId: userInfo.userId,
};
};
}
12 changes: 0 additions & 12 deletions packages/core/src/events.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { getUUID } from './uuid';

import {
GroupEventType,
GroupTraits,
Expand All @@ -10,7 +8,6 @@ import {
UserTraits,
AliasEventType,
EventType,
SegmentEvent,
} from './types';

export const createTrackEvent = ({
Expand Down Expand Up @@ -76,12 +73,3 @@ export const createAliasEvent = ({
userId: newUserId,
previousId: userId ?? anonymousId,
});

export const applyRawEventData = (event: SegmentEvent): SegmentEvent => {
return {
...event,
messageId: getUUID(),
timestamp: new Date().toISOString(),
integrations: event.integrations ?? {},
};
};
18 changes: 0 additions & 18 deletions packages/core/src/plugins/InjectContext.ts

This file was deleted.

69 changes: 0 additions & 69 deletions packages/core/src/plugins/InjectUserInfo.ts

This file was deleted.

Loading