Skip to content

Commit

Permalink
[FSSDK-10090] Refactor ODP integration (#920)
Browse files Browse the repository at this point in the history
* refactor

* refactor: build working

* fix segment manager tests

* fix identify user

* update event api manager

* update event man

* add sement manager test

* fix odp event manager tests

* odp manager tests

* fix odp event manager tests

* odpManager tests

* odp manager tests

* browserOdpManager tests fixed

* fix project config tests

* fix tests

* fix

* config manager tests fix

* odpManager test

* event man update

* copyright

* remove console log

* fix review

* undo clear timeout

* remove unnecessary line
  • Loading branch information
raju-opti authored Apr 5, 2024
1 parent 53a2042 commit 75a0148
Show file tree
Hide file tree
Showing 29 changed files with 1,624 additions and 1,081 deletions.
112 changes: 37 additions & 75 deletions lib/core/odp/odp_config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Copyright 2022-2023, Optimizely
* Copyright 2022-2024, Optimizely
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -19,90 +19,29 @@ import { checkArrayEquality } from '../../utils/fns';
export class OdpConfig {
/**
* Host of ODP audience segments API.
* @private
*/
private _apiHost: string;

/**
* Getter to retrieve the ODP server host
* @public
*/
get apiHost(): string {
return this._apiHost;
}
readonly apiHost: string;

/**
* Public API key for the ODP account from which the audience segments will be fetched (optional).
* @private
*/
private _apiKey: string;

/**
* Getter to retrieve the ODP API key
* @public
*/
get apiKey(): string {
return this._apiKey;
}
readonly apiKey: string;

/**
* Url for sending events via pixel.
* @private
*/
private _pixelUrl: string;

/**
* Getter to retrieve the ODP pixel URL
* @public
*/
get pixelUrl(): string {
return this._pixelUrl;
}
readonly pixelUrl: string;

/**
* All ODP segments used in the current datafile (associated with apiHost/apiKey).
* @private
*/
private _segmentsToCheck: string[];

/**
* Getter for ODP segments to check
* @public
*/
get segmentsToCheck(): string[] {
return this._segmentsToCheck;
}

constructor(apiKey?: string, apiHost?: string, pixelUrl?: string, segmentsToCheck?: string[]) {
this._apiKey = apiKey ?? '';
this._apiHost = apiHost ?? '';
this._pixelUrl = pixelUrl ?? '';
this._segmentsToCheck = segmentsToCheck ?? [];
}

/**
* Update the ODP configuration details
* @param {OdpConfig} config New ODP Config to potentially update self with
* @returns true if configuration was updated successfully
*/
update(config: OdpConfig): boolean {
if (this.equals(config)) {
return false;
} else {
if (config.apiKey) this._apiKey = config.apiKey;
if (config.apiHost) this._apiHost = config.apiHost;
if (config.pixelUrl) this._pixelUrl = config.pixelUrl;
if (config.segmentsToCheck) this._segmentsToCheck = config.segmentsToCheck;
readonly segmentsToCheck: string[];

return true;
}
}

/**
* Determines if ODP configuration has the minimum amount of information
*/
isReady(): boolean {
return !!this._apiKey && !!this._apiHost;
constructor(apiKey: string, apiHost: string, pixelUrl: string, segmentsToCheck: string[]) {
this.apiKey = apiKey;
this.apiHost = apiHost;
this.pixelUrl = pixelUrl;
this.segmentsToCheck = segmentsToCheck;
}

/**
Expand All @@ -112,10 +51,33 @@ export class OdpConfig {
*/
equals(configToCompare: OdpConfig): boolean {
return (
this._apiHost === configToCompare._apiHost &&
this._apiKey === configToCompare._apiKey &&
this._pixelUrl === configToCompare._pixelUrl &&
checkArrayEquality(this.segmentsToCheck, configToCompare._segmentsToCheck)
this.apiHost === configToCompare.apiHost &&
this.apiKey === configToCompare.apiKey &&
this.pixelUrl === configToCompare.pixelUrl &&
checkArrayEquality(this.segmentsToCheck, configToCompare.segmentsToCheck)
);
}
}

export type OdpNotIntegratedConfig = {
readonly integrated: false;
}

export type OdpIntegratedConfig = {
readonly integrated: true;
readonly odpConfig: OdpConfig;
}

export const odpIntegrationsAreEqual = (config1: OdpIntegrationConfig, config2: OdpIntegrationConfig): boolean => {
if (config1.integrated !== config2.integrated) {
return false;
}

if (config1.integrated && config2.integrated) {
return config1.odpConfig.equals(config2.odpConfig);
}

return true;
}

export type OdpIntegrationConfig = OdpNotIntegratedConfig | OdpIntegratedConfig;
30 changes: 6 additions & 24 deletions lib/core/odp/odp_event_api_manager.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Copyright 2022-2023, Optimizely
* Copyright 2022-2024, Optimizely
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -18,16 +18,15 @@ import { LogHandler, LogLevel } from '../../modules/logging';
import { OdpEvent } from './odp_event';
import { RequestHandler } from '../../utils/http_request_handler/http';
import { OdpConfig } from './odp_config';
import { ERROR_MESSAGES } from '../../utils/enums';

const EVENT_SENDING_FAILURE_MESSAGE = 'ODP event send failed';
export const ODP_CONFIG_NOT_READY_MESSAGE = 'ODP config not ready';

/**
* Manager for communicating with the Optimizely Data Platform REST API
*/
export interface IOdpEventApiManager {
sendEvents(events: OdpEvent[]): Promise<boolean>;
updateSettings(odpConfig: OdpConfig): void;
sendEvents(odpConfig: OdpConfig, events: OdpEvent[]): Promise<boolean>;
}

/**
Expand All @@ -46,11 +45,6 @@ export abstract class OdpEventApiManager implements IOdpEventApiManager {
*/
private readonly requestHandler: RequestHandler;

/**
* ODP configuration settings for identifying the target API and segments
*/
protected odpConfig?: OdpConfig;

/**
* Creates instance to access Optimizely Data Platform (ODP) REST API
* @param requestHandler Desired request handler for testing
Expand All @@ -61,14 +55,6 @@ export abstract class OdpEventApiManager implements IOdpEventApiManager {
this.logger = logger;
}

/**
* Updates odpConfig of the api manager instance
* @param odpConfig
*/
updateSettings(odpConfig: OdpConfig): void {
this.odpConfig = odpConfig;
}

getLogger(): LogHandler {
return this.logger;
}
Expand All @@ -78,14 +64,9 @@ export abstract class OdpEventApiManager implements IOdpEventApiManager {
* @param events ODP events to send
* @returns Retry is true - if network or server error (5xx), otherwise false
*/
async sendEvents(events: OdpEvent[]): Promise<boolean> {
async sendEvents(odpConfig: OdpConfig, events: OdpEvent[]): Promise<boolean> {
let shouldRetry = false;

if (!this.odpConfig?.isReady()) {
this.logger.log(LogLevel.ERROR, `${EVENT_SENDING_FAILURE_MESSAGE} (${ODP_CONFIG_NOT_READY_MESSAGE})`);
return shouldRetry;
}

if (events.length === 0) {
this.logger.log(LogLevel.ERROR, `${EVENT_SENDING_FAILURE_MESSAGE} (no events)`);
return shouldRetry;
Expand All @@ -95,7 +76,7 @@ export abstract class OdpEventApiManager implements IOdpEventApiManager {
return shouldRetry;
}

const { method, endpoint, headers, data } = this.generateRequestData(events);
const { method, endpoint, headers, data } = this.generateRequestData(odpConfig, events);

let statusCode = 0;
try {
Expand Down Expand Up @@ -125,6 +106,7 @@ export abstract class OdpEventApiManager implements IOdpEventApiManager {
protected abstract shouldSendEvents(events: OdpEvent[]): boolean;

protected abstract generateRequestData(
odpConfig: OdpConfig,
events: OdpEvent[]
): {
method: string;
Expand Down
Loading

0 comments on commit 75a0148

Please sign in to comment.