Skip to content

Commit 082c086

Browse files
authored
fix(ats): [FSSDK-9114] Various Fixes for FSC (#818)
Note: Still missing fix for event dispatch issue in FSC. Will resolve in a later patch.
1 parent 34a7bf0 commit 082c086

23 files changed

+1201
-872
lines changed

packages/optimizely-sdk/lib/core/odp/odp_event_manager.ts

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,10 @@ import { ERROR_MESSAGES, ODP_USER_KEY, ODP_DEFAULT_EVENT_TYPE, ODP_EVENT_ACTION
2121

2222
import { OdpEvent } from './odp_event';
2323
import { OdpConfig } from './odp_config';
24-
import { OdpEventApiManager } from './odp_event_api_manager';
24+
import { IOdpEventApiManager } from './odp_event_api_manager';
2525
import { invalidOdpDataFound } from './odp_utils';
2626

2727
const MAX_RETRIES = 3;
28-
const DEFAULT_BATCH_SIZE = 10;
29-
const DEFAULT_FLUSH_INTERVAL_MSECS = 1000;
30-
const DEFAULT_BROWSER_QUEUE_SIZE = 100;
31-
const DEFAULT_SERVER_QUEUE_SIZE = 10000;
3228

3329
/**
3430
* Event dispatcher's execution states
@@ -51,7 +47,7 @@ export interface IOdpEventManager {
5147

5248
registerVuid(vuid: string): void;
5349

54-
identifyUser(userId: string, vuid?: string): void;
50+
identifyUser(userId?: string, vuid?: string): void;
5551

5652
sendEvent(event: OdpEvent): void;
5753

@@ -85,7 +81,7 @@ export abstract class OdpEventManager implements IOdpEventManager {
8581
* REST API Manager used to send the events
8682
* @private
8783
*/
88-
private readonly apiManager: OdpEventApiManager;
84+
private readonly apiManager: IOdpEventApiManager;
8985
/**
9086
* Handler for recording execution logs
9187
* @private
@@ -100,7 +96,7 @@ export abstract class OdpEventManager implements IOdpEventManager {
10096
* Maximum number of events to process at once. Ignored in browser context
10197
* @protected
10298
*/
103-
protected batchSize!: number;
99+
protected batchSize!: number;
104100
/**
105101
* Milliseconds between setTimeout() to process new batches. Ignored in browser context
106102
* @protected
@@ -128,7 +124,7 @@ export abstract class OdpEventManager implements IOdpEventManager {
128124
flushInterval,
129125
}: {
130126
odpConfig: OdpConfig;
131-
apiManager: OdpEventApiManager;
127+
apiManager: IOdpEventApiManager;
132128
logger: LogHandler;
133129
clientEngine: string;
134130
clientVersion: string;
@@ -148,7 +144,7 @@ export abstract class OdpEventManager implements IOdpEventManager {
148144
protected abstract initParams(
149145
batchSize: number | undefined,
150146
queueSize: number | undefined,
151-
flushInterval: number | undefined,
147+
flushInterval: number | undefined
152148
): void;
153149

154150
/**

packages/optimizely-sdk/lib/core/odp/odp_manager.ts

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,29 @@ import { ERROR_MESSAGES, ODP_USER_KEY } from '../../utils/enums';
2121
import { VuidManager } from '../../plugins/vuid_manager';
2222

2323
import { OdpConfig } from './odp_config';
24-
import { OdpEventManager } from './odp_event_manager';
25-
import { OdpSegmentManager } from './odp_segment_manager';
24+
import { IOdpEventManager } from './odp_event_manager';
25+
import { IOdpSegmentManager } from './odp_segment_manager';
2626
import { OptimizelySegmentOption } from './optimizely_segment_option';
2727
import { invalidOdpDataFound } from './odp_utils';
2828
import { OdpEvent } from './odp_event';
2929

30+
export interface IOdpManager {
31+
enabled: boolean;
32+
segmentManager: IOdpSegmentManager | undefined;
33+
eventManager: IOdpEventManager | undefined;
34+
updateSettings({ apiKey, apiHost, segmentsToCheck }: OdpConfig): boolean;
35+
close(): void;
36+
fetchQualifiedSegments(userId: string, options?: Array<OptimizelySegmentOption>): Promise<string[] | null>;
37+
identifyUser(userId?: string, vuid?: string): void;
38+
sendEvent({ type, action, identifiers, data }: OdpEvent): void;
39+
isVuidEnabled(): boolean;
40+
getVuid(): string | undefined;
41+
}
42+
3043
/**
3144
* Orchestrates segments manager, event manager, and ODP configuration
3245
*/
33-
export abstract class OdpManager {
46+
export abstract class OdpManager implements IOdpManager {
3447
initPromise?: Promise<void>;
3548
enabled = true;
3649
logger: LogHandler = getLogger();
@@ -40,20 +53,20 @@ export abstract class OdpManager {
4053
* ODP Segment Manager which provides an interface to the remote ODP server (GraphQL API) for audience segments mapping.
4154
* It fetches all qualified segments for the given user context and manages the segments cache for all user contexts.
4255
*/
43-
public segmentManager: OdpSegmentManager | undefined;
56+
segmentManager: IOdpSegmentManager | undefined;
4457

4558
/**
4659
* ODP Event Manager which provides an interface to the remote ODP server (REST API) for events.
4760
* It will queue all pending events (persistent) and send them (in batches of up to 10 events) to the ODP server when possible.
4861
*/
49-
public eventManager: OdpEventManager | undefined;
62+
eventManager: IOdpEventManager | undefined;
5063

5164
constructor() {}
5265

5366
/**
5467
* Provides a method to update ODP Manager's ODP Config API Key, API Host, and Audience Segments
5568
*/
56-
public updateSettings({ apiKey, apiHost, segmentsToCheck }: OdpConfig): boolean {
69+
updateSettings({ apiKey, apiHost, segmentsToCheck }: OdpConfig): boolean {
5770
if (!this.enabled) {
5871
return false;
5972
}
@@ -85,7 +98,7 @@ export abstract class OdpManager {
8598
/**
8699
* Attempts to stop the current instance of ODP Manager's event manager, if it exists and is running.
87100
*/
88-
public close(): void {
101+
close(): void {
89102
if (!this.enabled) {
90103
return;
91104
}
@@ -100,10 +113,7 @@ export abstract class OdpManager {
100113
* @param {Array<OptimizelySegmentOption>} options - An array of OptimizelySegmentOption used to ignore and/or reset the cache.
101114
* @returns {Promise<string[] | null>} A promise holding either a list of qualified segments or null.
102115
*/
103-
public async fetchQualifiedSegments(
104-
userId: string,
105-
options: Array<OptimizelySegmentOption> = []
106-
): Promise<string[] | null> {
116+
async fetchQualifiedSegments(userId: string, options: Array<OptimizelySegmentOption> = []): Promise<string[] | null> {
107117
if (!this.enabled) {
108118
this.logger.log(LogLevel.ERROR, ERROR_MESSAGES.ODP_NOT_ENABLED);
109119
return null;
@@ -127,7 +137,7 @@ export abstract class OdpManager {
127137
* @param {string} vuid (Optional) Secondary unique identifier of a target user, primarily used by client SDKs.
128138
* @returns
129139
*/
130-
public identifyUser(userId?: string, vuid?: string): void {
140+
identifyUser(userId?: string, vuid?: string): void {
131141
if (!this.enabled) {
132142
this.logger.log(LogLevel.DEBUG, LOG_MESSAGES.ODP_IDENTIFY_FAILED_ODP_DISABLED);
133143
return;
@@ -155,7 +165,13 @@ export abstract class OdpManager {
155165
* Sends an event to the ODP Server via the ODP Events API
156166
* @param {OdpEvent} > ODP Event to send to event manager
157167
*/
158-
public sendEvent({ type, action, identifiers, data }: OdpEvent): void {
168+
sendEvent({ type, action, identifiers, data }: OdpEvent): void {
169+
let mType = type;
170+
171+
if (typeof mType !== 'string' || mType === '') {
172+
mType = 'fullstack';
173+
}
174+
159175
if (!this.enabled) {
160176
throw new Error(ERROR_MESSAGES.ODP_NOT_ENABLED);
161177
}
@@ -172,10 +188,14 @@ export abstract class OdpManager {
172188
throw new Error(ERROR_MESSAGES.ODP_SEND_EVENT_FAILED_EVENT_MANAGER_MISSING);
173189
}
174190

175-
this.eventManager.sendEvent(new OdpEvent(type, action, identifiers, data));
191+
if (typeof action !== 'string' || action === '') {
192+
throw new Error('ODP action is not valid (cannot be empty).');
193+
}
194+
195+
this.eventManager.sendEvent(new OdpEvent(mType, action, identifiers, data));
176196
}
177197

178-
public abstract isVuidEnabled(): boolean;
198+
abstract isVuidEnabled(): boolean;
179199

180-
public abstract getVuid(): string | undefined;
200+
abstract getVuid(): string | undefined;
181201
}

packages/optimizely-sdk/lib/core/odp/odp_segment_manager.ts

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,26 @@
1616

1717
import { getLogger, LogHandler, LogLevel } from '../../modules/logging';
1818
import { ERROR_MESSAGES, ODP_USER_KEY } from '../../utils/enums';
19-
import { LRUCache } from '../../utils/lru_cache';
20-
import { OdpSegmentApiManager } from './odp_segment_api_manager';
19+
import { ICache } from '../../utils/lru_cache';
20+
import { IOdpSegmentApiManager } from './odp_segment_api_manager';
2121
import { OdpConfig } from './odp_config';
2222
import { OptimizelySegmentOption } from './optimizely_segment_option';
2323

24+
export interface IOdpSegmentManager {
25+
fetchQualifiedSegments(
26+
userKey: ODP_USER_KEY,
27+
userValue: string,
28+
options: Array<OptimizelySegmentOption>
29+
): Promise<string[] | null>;
30+
reset(): void;
31+
makeCacheKey(userKey: string, userValue: string): string;
32+
updateSettings(config: OdpConfig): void;
33+
}
34+
2435
/**
2536
* Schedules connections to ODP for audience segmentation and caches the results.
2637
*/
27-
export class OdpSegmentManager {
38+
export class OdpSegmentManager implements IOdpSegmentManager {
2839
/**
2940
* ODP configuration settings in used
3041
* @private
@@ -35,21 +46,21 @@ export class OdpSegmentManager {
3546
* Holds cached audience segments
3647
* @private
3748
*/
38-
private _segmentsCache: LRUCache<string, string[]>;
49+
private _segmentsCache: ICache<string, string[]>;
3950

4051
/**
4152
* Getter for private segments cache
4253
* @public
4354
*/
44-
public get segmentsCache(): LRUCache<string, string[]> {
55+
public get segmentsCache(): ICache<string, string[]> {
4556
return this._segmentsCache;
4657
}
4758

4859
/**
4960
* GraphQL API Manager used to fetch segments
5061
* @private
5162
*/
52-
private odpSegmentApiManager: OdpSegmentApiManager;
63+
private odpSegmentApiManager: IOdpSegmentApiManager;
5364

5465
/**
5566
* Handler for recording execution logs
@@ -59,8 +70,8 @@ export class OdpSegmentManager {
5970

6071
constructor(
6172
odpConfig: OdpConfig,
62-
segmentsCache: LRUCache<string, string[]>,
63-
odpSegmentApiManager: OdpSegmentApiManager,
73+
segmentsCache: ICache<string, string[]>,
74+
odpSegmentApiManager: IOdpSegmentApiManager,
6475
logger?: LogHandler
6576
) {
6677
this.odpConfig = odpConfig;
@@ -100,7 +111,9 @@ export class OdpSegmentManager {
100111
const ignoreCache = options.includes(OptimizelySegmentOption.IGNORE_CACHE);
101112
const resetCache = options.includes(OptimizelySegmentOption.RESET_CACHE);
102113

103-
if (resetCache) this.reset();
114+
if (resetCache) {
115+
this.reset();
116+
}
104117

105118
if (!ignoreCache && !resetCache) {
106119
const cachedSegments = this._segmentsCache.lookup(cacheKey);
@@ -121,7 +134,9 @@ export class OdpSegmentManager {
121134
segmentsToCheck
122135
);
123136

124-
if (segments && !ignoreCache) this._segmentsCache.save({ key: cacheKey, value: segments });
137+
if (segments && !ignoreCache) {
138+
this._segmentsCache.save({ key: cacheKey, value: segments });
139+
}
125140

126141
return segments;
127142
}
@@ -149,5 +164,6 @@ export class OdpSegmentManager {
149164
*/
150165
public updateSettings(config: OdpConfig): void {
151166
this.odpConfig = config;
167+
this._segmentsCache.reset();
152168
}
153169
}

packages/optimizely-sdk/lib/core/odp/optimizely_segment_option.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,6 @@
1616

1717
// Options for defining behavior of OdpSegmentManager's caching mechanism when calling fetchSegments()
1818
export enum OptimizelySegmentOption {
19-
IGNORE_CACHE,
20-
RESET_CACHE,
19+
IGNORE_CACHE = 'IGNORE_CACHE',
20+
RESET_CACHE = 'RESET_CACHE',
2121
}

0 commit comments

Comments
 (0)