Skip to content

Commit

Permalink
Merge branch 'main' into rlamb/sdk-710/automatic-start-streaming
Browse files Browse the repository at this point in the history
  • Loading branch information
kinyoklion committed Sep 25, 2024
2 parents 5a3c8b4 + 53f5bb8 commit 65e68cd
Show file tree
Hide file tree
Showing 12 changed files with 92 additions and 62 deletions.
1 change: 0 additions & 1 deletion packages/sdk/browser/src/BrowserClient.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import {
AutoEnvAttributes,
base64UrlEncode,
BasicLogger,
LDClient as CommonClient,
Configuration,
createSafeLogger,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
} from '@launchdarkly/js-sdk-common';
import { createBasicPlatform, createLogger } from '@launchdarkly/private-js-mocks';

import Configuration from '../../src/configuration';
import { Configuration, ConfigurationImpl } from '../../src/configuration';
import {
addApplicationInfo,
addAutoEnv,
Expand All @@ -31,7 +31,7 @@ describe('automatic environment attributes', () => {
beforeEach(() => {
({ crypto, info } = mockPlatform);
(crypto.randomUUID as jest.Mock).mockResolvedValue('test-device-key-1');
config = new Configuration({ logger });
config = new ConfigurationImpl({ logger });
});

afterEach(() => {
Expand Down Expand Up @@ -338,7 +338,7 @@ describe('automatic environment attributes', () => {

describe('addApplicationInfo', () => {
test('add id, version, name, versionName', async () => {
config = new Configuration({
config = new ConfigurationImpl({
applicationInfo: {
id: 'com.from-config.ld',
version: '2.2.2',
Expand Down Expand Up @@ -431,7 +431,7 @@ describe('automatic environment attributes', () => {
info.platformData = jest
.fn()
.mockReturnValueOnce({ ld_application: { version: null, locale: '' } });
config = new Configuration({ applicationInfo: { version: '1.2.3' } });
config = new ConfigurationImpl({ applicationInfo: { version: '1.2.3' } });
const ldApplication = await addApplicationInfo(mockPlatform, config);

expect(ldApplication).toBeUndefined();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { secondsToMillis } from '@launchdarkly/js-sdk-common';

import Configuration from '../../src/configuration';
import { ConfigurationImpl } from '../../src/configuration';
import createDiagnosticsInitConfig, {
type DiagnosticsInitConfig,
} from '../../src/diagnostics/createDiagnosticsInitConfig';
Expand All @@ -9,7 +9,7 @@ describe('createDiagnosticsInitConfig', () => {
let initConfig: DiagnosticsInitConfig;

beforeEach(() => {
initConfig = createDiagnosticsInitConfig(new Configuration());
initConfig = createDiagnosticsInitConfig(new ConfigurationImpl());
});

test('defaults', () => {
Expand All @@ -29,7 +29,7 @@ describe('createDiagnosticsInitConfig', () => {

test('non-default config', () => {
const custom = createDiagnosticsInitConfig(
new Configuration({
new ConfigurationImpl({
baseUri: 'https://dev.ld.com',
streamUri: 'https://stream.ld.com',
eventsUri: 'https://events.ld.com',
Expand Down
17 changes: 17 additions & 0 deletions packages/shared/sdk-client/src/DataManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,20 @@ import { DataSourcePaths, StreamingProcessor } from './streaming';
import { DeleteFlag, Flags, PatchFlag } from './types';

export interface DataManager {
/**
* This function handles the data management aspects of the identification process.
*
* Implementation Note: The identifyResolve and identifyReject function resolve or reject the
* identify function at LDClient level. It is likely in individual implementations that these
* functions will be passed to other components, such as a datasource, do indicate when the
* identify process has been completed. The data manager identify function should return once
* everything has been set in motion to complete the identification process.
*
* @param identifyResolve Called to reject the identify operation.
* @param identifyReject Called to complete the identify operation.
* @param context The context being identified.
* @param identifyOptions Options for identification.
*/
identify(
identifyResolve: () => void,
identifyReject: (err: Error) => void,
Expand All @@ -28,6 +42,9 @@ export interface DataManager {
): Promise<void>;
}

/**
* Factory interface for constructing data managers.
*/
export interface DataManagerFactory {
(
flagManager: FlagManager,
Expand Down
5 changes: 2 additions & 3 deletions packages/shared/sdk-client/src/LDClientImpl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@ import {
import { LDClient, type LDOptions } from './api';
import { LDEvaluationDetail, LDEvaluationDetailTyped } from './api/LDEvaluationDetail';
import { LDIdentifyOptions } from './api/LDIdentifyOptions';
import ConfigurationImpl from './configuration';
import { LDClientInternalOptions } from './configuration/Configuration';
import { Configuration, ConfigurationImpl, LDClientInternalOptions } from './configuration';

Check failure on line 24 in packages/shared/sdk-client/src/LDClientImpl.ts

View workflow job for this annotation

GitHub Actions / build-test-sdk-client

'Configuration' is defined but never used. Allowed unused vars must match /^__/u
import { addAutoEnv } from './context/addAutoEnv';
import { ensureKey } from './context/ensureKey';
import { DataManager, DataManagerFactory } from './DataManager';
Expand All @@ -33,7 +32,7 @@ import {
} from './evaluation/evaluationDetail';
import createEventProcessor from './events/createEventProcessor';
import EventFactory from './events/EventFactory';
import DefaultFlagManager from './flag-manager/FlagManager';
import DefaultFlagManager, { FlagManager } from './flag-manager/FlagManager';

Check failure on line 35 in packages/shared/sdk-client/src/LDClientImpl.ts

View workflow job for this annotation

GitHub Actions / build-test-sdk-client

'FlagManager' is defined but never used. Allowed unused vars must match /^__/u
import { ItemDescriptor } from './flag-manager/ItemDescriptor';
import LDEmitter, { EventName } from './LDEmitter';
import { DeleteFlag, Flags, PatchFlag } from './types';
Expand Down
12 changes: 7 additions & 5 deletions packages/shared/sdk-client/src/configuration/Configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,15 +56,17 @@ export interface Configuration {
readonly trackEventModifier: (event: internal.InputCustomEvent) => internal.InputCustomEvent;
}

export default class ConfigurationImpl implements Configuration {
public static DEFAULT_POLLING = 'https://clientsdk.launchdarkly.com';
public static DEFAULT_STREAM = 'https://clientstream.launchdarkly.com';
const DEFAULT_POLLING: string = 'https://clientsdk.launchdarkly.com';
const DEFAULT_STREAM: string = 'https://clientstream.launchdarkly.com';

export { DEFAULT_POLLING, DEFAULT_STREAM };

export default class ConfigurationImpl implements Configuration {
public readonly logger: LDLogger = createSafeLogger();

public readonly baseUri = ConfigurationImpl.DEFAULT_POLLING;
public readonly baseUri = DEFAULT_POLLING;
public readonly eventsUri = ServiceEndpoints.DEFAULT_EVENTS;
public readonly streamUri = ConfigurationImpl.DEFAULT_STREAM;
public readonly streamUri = DEFAULT_STREAM;

public readonly maxCachedContexts = 5;

Expand Down
15 changes: 13 additions & 2 deletions packages/shared/sdk-client/src/configuration/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
import ConfigurationImpl from './Configuration';
import ConfigurationImpl, {
Configuration,
DEFAULT_POLLING,
DEFAULT_STREAM,
LDClientInternalOptions,
} from './Configuration';

export default ConfigurationImpl;
export {
Configuration,
ConfigurationImpl,
LDClientInternalOptions,
DEFAULT_POLLING,
DEFAULT_STREAM,
};
10 changes: 3 additions & 7 deletions packages/shared/sdk-client/src/context/addAutoEnv.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
Platform,
} from '@launchdarkly/js-sdk-common';

import ConfigurationImpl from '../configuration';
import { Configuration } from '../configuration';
import digest from '../crypto/digest';
import { getOrGenerateKey } from '../storage/getOrGenerateKey';
import { namespaceForGeneratedContextKey } from '../storage/namespaceUtils';
Expand Down Expand Up @@ -39,7 +39,7 @@ export const toMulti = (c: LDSingleKindContext) => {
*/
export const addApplicationInfo = async (
{ crypto, info }: Platform,
{ applicationInfo }: ConfigurationImpl,
{ applicationInfo }: Configuration,
): Promise<LDApplication | undefined> => {
const { ld_application } = info.platformData();
let app = deepCompact<LDApplication>(ld_application) ?? ({} as LDApplication);
Expand Down Expand Up @@ -103,11 +103,7 @@ export const addDeviceInfo = async (platform: Platform) => {
return undefined;
};

export const addAutoEnv = async (
context: LDContext,
platform: Platform,
config: ConfigurationImpl,
) => {
export const addAutoEnv = async (context: LDContext, platform: Platform, config: Configuration) => {
// LDUser is not supported for auto env reporting
if (isLegacyUser(context)) {
return context as LDUser;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { secondsToMillis, ServiceEndpoints } from '@launchdarkly/js-sdk-common';

import ConfigurationImpl from '../configuration';
import { Configuration, DEFAULT_POLLING, DEFAULT_STREAM } from '../configuration';

export type DiagnosticsInitConfig = {
// client & server common properties
Expand All @@ -17,9 +17,9 @@ export type DiagnosticsInitConfig = {
usingSecureMode: boolean;
bootstrapMode: boolean;
};
const createDiagnosticsInitConfig = (config: ConfigurationImpl): DiagnosticsInitConfig => ({
customBaseURI: config.baseUri !== ConfigurationImpl.DEFAULT_POLLING,
customStreamURI: config.streamUri !== ConfigurationImpl.DEFAULT_STREAM,
const createDiagnosticsInitConfig = (config: Configuration): DiagnosticsInitConfig => ({
customBaseURI: config.baseUri !== DEFAULT_POLLING,
customStreamURI: config.streamUri !== DEFAULT_STREAM,
customEventsURI: config.eventsUri !== ServiceEndpoints.DEFAULT_EVENTS,
eventsCapacity: config.capacity,
eventsFlushIntervalMillis: secondsToMillis(config.flushInterval),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { internal, Platform } from '@launchdarkly/js-sdk-common';

import ConfigurationImpl from '../configuration';
import { Configuration } from '../configuration';
import createDiagnosticsInitConfig from './createDiagnosticsInitConfig';

const createDiagnosticsManager = (
clientSideID: string,
config: ConfigurationImpl,
config: Configuration,
platform: Platform,
) => {
if (config.sendEvents && !config.diagnosticOptOut) {
Expand Down
4 changes: 2 additions & 2 deletions packages/shared/sdk-client/src/events/createEventProcessor.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { ClientContext, internal, LDHeaders, Platform } from '@launchdarkly/js-sdk-common';

import ConfigurationImpl from '../configuration';
import { Configuration } from '../configuration';

const createEventProcessor = (
clientSideID: string,
config: ConfigurationImpl,
config: Configuration,
platform: Platform,
baseHeaders: LDHeaders,
diagnosticsManager?: internal.DiagnosticsManager,
Expand Down
64 changes: 35 additions & 29 deletions packages/shared/sdk-client/src/flag-manager/FlagManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,51 @@ import { DefaultFlagStore } from './FlagStore';
import FlagUpdater, { FlagsChangeCallback } from './FlagUpdater';
import { ItemDescriptor } from './ItemDescriptor';

/**
* Top level manager of flags for the client. LDClient should be using this
* interface and not any of the specific instances managed by it. Updates from
* data sources should be directed to the [init] and [upsert] methods of this
* interface.
*/
export interface FlagManager {
/**
* Attempts to get a flag by key from the current flags.
*/
get(key: string): ItemDescriptor | undefined;

/**
* Gets all the current flags.
*/
getAll(): { [key: string]: ItemDescriptor };

/**
* Initializes the flag manager with data from a data source.
* Persistence initialization is handled by {@link FlagPersistence}
*/
init(context: Context, newFlags: { [key: string]: ItemDescriptor }): Promise<void>;

/**
* Attempt to update a flag. If the flag is for the wrong context, or
* it is of an older version, then an update will not be performed.
*/
upsert(context: Context, key: string, item: ItemDescriptor): Promise<boolean>;

/**
* Asynchronously load cached values from persistence.
*/
loadCached(context: Context): Promise<boolean>;

/**
* Register a flag change callback.
*/
on(callback: FlagsChangeCallback): void;

/**
* Unregister a flag change callback.
*/
off(callback: FlagsChangeCallback): void;
}

/**
* Top level manager of flags for the client. LDClient should be using this
* class and not any of the specific instances managed by it. Updates from
* data sources should be directed to the [init] and [upsert] methods of this
* class.
*/
export default class DefaultFlagManager implements FlagManager {
private flagStore = new DefaultFlagStore();
private flagUpdater: FlagUpdater;
Expand Down Expand Up @@ -71,53 +100,30 @@ export default class DefaultFlagManager implements FlagManager {
);
}

/**
* Attempts to get a flag by key from the current flags.
*/
get(key: string): ItemDescriptor | undefined {
return this.flagStore.get(key);
}

/**
* Gets all the current flags.
*/
getAll(): { [key: string]: ItemDescriptor } {
return this.flagStore.getAll();
}

/**
* Initializes the flag manager with data from a data source.
* Persistence initialization is handled by {@link FlagPersistence}
*/
async init(context: Context, newFlags: { [key: string]: ItemDescriptor }): Promise<void> {
return (await this.flagPersistencePromise).init(context, newFlags);
}

/**
* Attempt to update a flag. If the flag is for the wrong context, or
* it is of an older version, then an update will not be performed.
*/
async upsert(context: Context, key: string, item: ItemDescriptor): Promise<boolean> {
return (await this.flagPersistencePromise).upsert(context, key, item);
}

/**
* Asynchronously load cached values from persistence.
*/
async loadCached(context: Context): Promise<boolean> {
return (await this.flagPersistencePromise).loadCached(context);
}

/**
* Register a flag change callback.
*/
on(callback: FlagsChangeCallback): void {
this.flagUpdater.on(callback);
}

/**
* Unregister a flag change callback.
*/
off(callback: FlagsChangeCallback): void {
this.flagUpdater.off(callback);
}
Expand Down

0 comments on commit 65e68cd

Please sign in to comment.