From c7b9ddbcc5f48ee007ed39b05513b2e8a71f75ac Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Wed, 27 Apr 2022 12:12:00 -0300 Subject: [PATCH 1/4] simplify interfaces of factory internal components --- src/sdkFactory/index.ts | 30 +++++++---------- src/sdkFactory/types.ts | 43 +++++++++++++++++-------- src/sync/offline/syncManagerOffline.ts | 7 ++-- src/sync/polling/pollingManagerCS.ts | 4 +-- src/sync/polling/pollingManagerSS.ts | 4 +-- src/sync/streaming/pushManager.ts | 4 +-- src/sync/submitters/submitterManager.ts | 4 +-- src/sync/syncManagerOnline.ts | 11 ++++--- src/sync/types.ts | 13 -------- src/types.ts | 5 +-- 10 files changed, 62 insertions(+), 63 deletions(-) diff --git a/src/sdkFactory/index.ts b/src/sdkFactory/index.ts index ce77472a..bb5070d0 100644 --- a/src/sdkFactory/index.ts +++ b/src/sdkFactory/index.ts @@ -1,11 +1,10 @@ -import { ISdkFactoryParams } from './types'; +import { ISdkFactoryContext, ISdkFactoryContextSync, ISdkFactoryParams } from './types'; import { sdkReadinessManagerFactory } from '../readiness/sdkReadinessManager'; import { impressionsTrackerFactory } from '../trackers/impressionsTracker'; import { eventTrackerFactory } from '../trackers/eventTracker'; import { telemetryTrackerFactory } from '../trackers/telemetryTracker'; -import { IStorageFactoryParams, IStorageSync } from '../storages/types'; +import { IStorageFactoryParams } from '../storages/types'; import { SplitIO } from '../types'; -import { ISplitApi } from '../services/types'; import { getMatching } from '../utils/key'; import { shouldBeOptimized } from '../trackers/impressionObserver/utils'; import { validateAndTrackApiKey } from '../utils/inputValidation/apiKey'; @@ -32,7 +31,7 @@ export function sdkFactory(params: ISdkFactoryParams): SplitIO.ICsSDK | SplitIO. validateAndTrackApiKey(log, settings.core.authorizationKey); const sdkReadinessManager = sdkReadinessManagerFactory(log, platform.EventEmitter, settings.startup.readyTimeout); - const readinessManager = sdkReadinessManager.readinessManager; + const readiness = sdkReadinessManager.readinessManager; // @TODO consider passing the settings object, so that each storage access only what it needs const storageFactoryParams: IStorageFactoryParams = { @@ -51,8 +50,8 @@ export function sdkFactory(params: ISdkFactoryParams): SplitIO.ICsSDK | SplitIO. // or partial consumer mode, where it only has submitters, and therefore it doesn't emit readiness events. onReadyCb: (error) => { if (error) return; // Don't emit SDK_READY if storage failed to connect. Error message is logged by wrapperAdapter - readinessManager.splits.emit(SDK_SPLITS_ARRIVED); - readinessManager.segments.emit(SDK_SEGMENTS_ARRIVED); + readiness.splits.emit(SDK_SPLITS_ARRIVED); + readiness.segments.emit(SDK_SEGMENTS_ARRIVED); }, metadata: metadataBuilder(settings), log @@ -72,20 +71,15 @@ export function sdkFactory(params: ISdkFactoryParams): SplitIO.ICsSDK | SplitIO. // splitApi is used by SyncManager and Browser signal listener const splitApi = splitApiFactory && splitApiFactory(settings, platform); - const syncManager = syncManagerFactory && syncManagerFactory({ - settings, - splitApi: splitApi as ISplitApi, - storage: storage as IStorageSync, - readiness: sdkReadinessManager.readinessManager, - platform, - telemetryTracker - }); - - // signal listener + const ctx: ISdkFactoryContext = { splitApi, eventTracker, impressionsTracker, telemetryTracker, sdkReadinessManager, readiness, settings, storage, platform }; + + const syncManager = syncManagerFactory && syncManagerFactory(ctx as ISdkFactoryContextSync); + ctx.syncManager = syncManager; + const signalListener = SignalListener && new SignalListener(syncManager, settings, storage, splitApi); + ctx.signalListener = signalListener; - // Sdk client and manager - const ctx = { eventTracker, impressionsTracker, telemetryTracker, sdkReadinessManager, settings, storage, syncManager, signalListener }; + // SDK client and manager const clientMethod = sdkClientMethodFactory(ctx); const managerInstance = sdkManagerFactory(log, storage.splits, sdkReadinessManager); diff --git a/src/sdkFactory/types.ts b/src/sdkFactory/types.ts index 8781ae0c..9d0700ef 100644 --- a/src/sdkFactory/types.ts +++ b/src/sdkFactory/types.ts @@ -1,25 +1,14 @@ import { IIntegrationManager, IIntegrationFactoryParams } from '../integrations/types'; import { ISignalListener } from '../listeners/types'; import { ILogger } from '../logger/types'; -import { ISdkReadinessManager } from '../readiness/types'; +import { IReadinessManager, ISdkReadinessManager } from '../readiness/types'; import { IFetch, ISplitApi, IEventSourceConstructor } from '../services/types'; import { IStorageAsync, IStorageSync, ISplitsCacheSync, ISplitsCacheAsync, IStorageFactoryParams } from '../storages/types'; -import { ISyncManager, ISyncManagerFactoryParams } from '../sync/types'; +import { ISyncManager } from '../sync/types'; import { IImpressionObserver } from '../trackers/impressionObserver/types'; import { IImpressionsTracker, IEventTracker, ITelemetryTracker } from '../trackers/types'; import { SplitIO, ISettings, IEventEmitter } from '../types'; -export interface ISdkFactoryContext { - storage: IStorageSync | IStorageAsync, - sdkReadinessManager: ISdkReadinessManager, - settings: ISettings - impressionsTracker: IImpressionsTracker, - eventTracker: IEventTracker, - telemetryTracker: ITelemetryTracker - signalListener?: ISignalListener - syncManager?: ISyncManager, -} - /** * Environment related dependencies. * These getters are called a fixed number of times per factory instantiation. @@ -32,6 +21,32 @@ export interface IPlatform { now?: () => number } +export interface ISdkFactoryContext { + platform: IPlatform, + sdkReadinessManager: ISdkReadinessManager, + readiness: IReadinessManager, + settings: ISettings + impressionsTracker: IImpressionsTracker, + eventTracker: IEventTracker, + telemetryTracker: ITelemetryTracker, + storage: IStorageSync | IStorageAsync, + signalListener?: ISignalListener + splitApi?: ISplitApi + syncManager?: ISyncManager, +} + +export interface ISdkFactoryContextSync extends ISdkFactoryContext { + storage: IStorageSync, + splitApi: ISplitApi + syncManager: ISyncManager, +} + +export interface ISdkFactoryContextAsync extends ISdkFactoryContext { + storage: IStorageAsync, + splitApi: undefined, + syncManager: undefined +} + /** * Object parameter with the modules required to create an SDK factory instance */ @@ -54,7 +69,7 @@ export interface ISdkFactoryParams { // SyncManager factory. // Not required when providing an asynchronous storage (consumer mode), but required in standalone mode to avoid SDK timeout. // It can create an offline or online sync manager, with or without streaming support. - syncManagerFactory?: (params: ISyncManagerFactoryParams) => ISyncManager, + syncManagerFactory?: (params: ISdkFactoryContextSync) => ISyncManager, // Sdk manager factory sdkManagerFactory: ( diff --git a/src/sync/offline/syncManagerOffline.ts b/src/sync/offline/syncManagerOffline.ts index 253493f2..cd5c435d 100644 --- a/src/sync/offline/syncManagerOffline.ts +++ b/src/sync/offline/syncManagerOffline.ts @@ -1,9 +1,10 @@ -import { ISyncManager, ISyncManagerCS, ISyncManagerFactoryParams } from '../types'; +import { ISyncManager, ISyncManagerCS } from '../types'; import { fromObjectSyncTaskFactory } from './syncTasks/fromObjectSyncTask'; import { objectAssign } from '../../utils/lang/objectAssign'; import { ISplitsParser } from './splitsParser/types'; import { IReadinessManager } from '../../readiness/types'; import { SDK_SEGMENTS_ARRIVED } from '../../readiness/constants'; +import { ISdkFactoryContextSync } from '../../sdkFactory/types'; function flush() { return Promise.resolve(); @@ -17,7 +18,7 @@ function flush() { */ export function syncManagerOfflineFactory( splitsParserFactory: () => ISplitsParser -): (params: ISyncManagerFactoryParams) => ISyncManagerCS { +): (params: ISdkFactoryContextSync) => ISyncManagerCS { /** * SyncManager factory for modular SDK @@ -26,7 +27,7 @@ export function syncManagerOfflineFactory( settings, readiness, storage, - }: ISyncManagerFactoryParams): ISyncManagerCS { + }: ISdkFactoryContextSync): ISyncManagerCS { return objectAssign( fromObjectSyncTaskFactory(splitsParserFactory(), storage, readiness, settings), diff --git a/src/sync/polling/pollingManagerCS.ts b/src/sync/polling/pollingManagerCS.ts index 364829a5..af1e82ca 100644 --- a/src/sync/polling/pollingManagerCS.ts +++ b/src/sync/polling/pollingManagerCS.ts @@ -7,14 +7,14 @@ import { splitsSyncTaskFactory } from './syncTasks/splitsSyncTask'; import { getMatching } from '../../utils/key'; import { SDK_SPLITS_ARRIVED, SDK_SEGMENTS_ARRIVED } from '../../readiness/constants'; import { POLLING_SMART_PAUSING, POLLING_START, POLLING_STOP } from '../../logger/constants'; -import { ISyncManagerFactoryParams } from '../types'; +import { ISdkFactoryContextSync } from '../../sdkFactory/types'; /** * Expose start / stop mechanism for polling data from services. * For client-side API with multiple clients. */ export function pollingManagerCSFactory( - params: ISyncManagerFactoryParams + params: ISdkFactoryContextSync ): IPollingManagerCS { const { splitApi, storage, readiness, settings } = params; diff --git a/src/sync/polling/pollingManagerSS.ts b/src/sync/polling/pollingManagerSS.ts index 2c7d3ec9..90f252a4 100644 --- a/src/sync/polling/pollingManagerSS.ts +++ b/src/sync/polling/pollingManagerSS.ts @@ -3,13 +3,13 @@ import { segmentsSyncTaskFactory } from './syncTasks/segmentsSyncTask'; import { IPollingManager, ISegmentsSyncTask, ISplitsSyncTask } from './types'; import { thenable } from '../../utils/promise/thenable'; import { POLLING_START, POLLING_STOP, LOG_PREFIX_SYNC_POLLING } from '../../logger/constants'; -import { ISyncManagerFactoryParams } from '../types'; +import { ISdkFactoryContextSync } from '../../sdkFactory/types'; /** * Expose start / stop mechanism for pulling data from services. */ export function pollingManagerSSFactory( - params: ISyncManagerFactoryParams + params: ISdkFactoryContextSync ): IPollingManager { const { splitApi, storage, readiness, settings } = params; diff --git a/src/sync/streaming/pushManager.ts b/src/sync/streaming/pushManager.ts index 0f9f9529..7f4625e9 100644 --- a/src/sync/streaming/pushManager.ts +++ b/src/sync/streaming/pushManager.ts @@ -18,8 +18,8 @@ import { isInBitmap, parseBitmap, parseKeyList } from './mySegmentsV2utils'; import { ISet, _Set } from '../../utils/lang/sets'; import { Hash64, hash64 } from '../../utils/murmur3/murmur3_64'; import { IAuthTokenPushEnabled } from './AuthClient/types'; -import { ISyncManagerFactoryParams } from '../types'; import { TOKEN_REFRESH, AUTH_REJECTION } from '../../utils/constants'; +import { ISdkFactoryContextSync } from '../../sdkFactory/types'; /** * PushManager factory: @@ -27,7 +27,7 @@ import { TOKEN_REFRESH, AUTH_REJECTION } from '../../utils/constants'; * - for client-side, with support for multiple clients, if key is provided in settings */ export function pushManagerFactory( - params: ISyncManagerFactoryParams, + params: ISdkFactoryContextSync, pollingManager: IPollingManager, ): IPushManager | undefined { diff --git a/src/sync/submitters/submitterManager.ts b/src/sync/submitters/submitterManager.ts index 51440a25..1eb531c9 100644 --- a/src/sync/submitters/submitterManager.ts +++ b/src/sync/submitters/submitterManager.ts @@ -2,9 +2,9 @@ import { syncTaskComposite } from '../syncTaskComposite'; import { eventsSyncTaskFactory } from './eventsSyncTask'; import { impressionsSyncTaskFactory } from './impressionsSyncTask'; import { impressionCountsSyncTaskFactory } from './impressionCountsSyncTask'; -import { ISyncManagerFactoryParams } from '../types'; +import { ISdkFactoryContextSync } from '../../sdkFactory/types'; -export function submitterManagerFactory(params: ISyncManagerFactoryParams) { +export function submitterManagerFactory(params: ISdkFactoryContextSync) { const { settings, storage, splitApi } = params; const log = settings.log; diff --git a/src/sync/syncManagerOnline.ts b/src/sync/syncManagerOnline.ts index 88c1516e..61f0603d 100644 --- a/src/sync/syncManagerOnline.ts +++ b/src/sync/syncManagerOnline.ts @@ -1,4 +1,4 @@ -import { ISyncManagerCS, ISyncManagerFactoryParams } from './types'; +import { ISyncManagerCS } from './types'; import { submitterManagerFactory } from './submitters/submitterManager'; import { IReadinessManager } from '../readiness/types'; import { IStorageSync } from '../storages/types'; @@ -8,6 +8,7 @@ import { PUSH_SUBSYSTEM_UP, PUSH_SUBSYSTEM_DOWN } from './streaming/constants'; import { SYNC_START_POLLING, SYNC_CONTINUE_POLLING, SYNC_STOP_POLLING } from '../logger/constants'; import { isConsentGranted } from '../consent'; import { POLLING, STREAMING, SYNC_MODE_UPDATE } from '../utils/constants'; +import { ISdkFactoryContextSync } from '../sdkFactory/types'; /** * Online SyncManager factory. @@ -18,14 +19,14 @@ import { POLLING, STREAMING, SYNC_MODE_UPDATE } from '../utils/constants'; * @param pushManagerFactory optional to build a SyncManager with or without streaming support */ export function syncManagerOnlineFactory( - pollingManagerFactory?: (params: ISyncManagerFactoryParams) => IPollingManager, - pushManagerFactory?: (params: ISyncManagerFactoryParams, pollingManager: IPollingManager) => IPushManager | undefined, -): (params: ISyncManagerFactoryParams) => ISyncManagerCS { + pollingManagerFactory?: (params: ISdkFactoryContextSync) => IPollingManager, + pushManagerFactory?: (params: ISdkFactoryContextSync, pollingManager: IPollingManager) => IPushManager | undefined, +): (params: ISdkFactoryContextSync) => ISyncManagerCS { /** * SyncManager factory for modular SDK */ - return function (params: ISyncManagerFactoryParams): ISyncManagerCS { + return function (params: ISdkFactoryContextSync): ISyncManagerCS { const { settings, settings: { log, streamingEnabled }, telemetryTracker } = params; diff --git a/src/sync/types.ts b/src/sync/types.ts index f2962885..53a25dae 100644 --- a/src/sync/types.ts +++ b/src/sync/types.ts @@ -1,9 +1,5 @@ import { IReadinessManager } from '../readiness/types'; -import { IPlatform } from '../sdkFactory/types'; -import { ISplitApi } from '../services/types'; import { IStorageSync } from '../storages/types'; -import { ITelemetryTracker } from '../trackers/types'; -import { ISettings } from '../types'; import { IPollingManager } from './polling/types'; import { IPushManager } from './streaming/types'; @@ -53,12 +49,3 @@ export interface ISyncManager extends ITask { export interface ISyncManagerCS extends ISyncManager { shared(matchingKey: string, readinessManager: IReadinessManager, storage: IStorageSync): ISyncManager | undefined } - -export interface ISyncManagerFactoryParams { - settings: ISettings, - readiness: IReadinessManager, - storage: IStorageSync, - splitApi: ISplitApi, - platform: IPlatform, - telemetryTracker: ITelemetryTracker -} diff --git a/src/types.ts b/src/types.ts index 6c5ba33e..1dc35037 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,10 +1,11 @@ import { ISplitFiltersValidation } from './dtos/types'; import { IIntegration, IIntegrationFactoryParams } from './integrations/types'; import { ILogger } from './logger/types'; +import { ISdkFactoryContext } from './sdkFactory/types'; /* eslint-disable no-use-before-define */ import { IStorageFactoryParams, IStorageSync, IStorageAsync, IStorageSyncFactory, IStorageAsyncFactory } from './storages/types'; -import { ISyncManagerFactoryParams, ISyncManagerCS } from './sync/types'; +import { ISyncManagerCS } from './sync/types'; /** * Reduced version of NodeJS.EventEmitter interface with the minimal methods used by the SDK @@ -611,7 +612,7 @@ export namespace SplitIO { */ export type LocalhostFactory = { type: 'LocalhostFromObject' | 'LocalhostFromFile' - (params: ISyncManagerFactoryParams): ISyncManagerCS + (params: ISdkFactoryContext): ISyncManagerCS } /** * Impression listener interface. This is the interface that needs to be implemented From a6193f36dbfc1203ada11a4842a1fee92651f5b6 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Thu, 28 Apr 2022 19:12:21 -0300 Subject: [PATCH 2/4] refactor submitters --- .../__tests__/eventsSubmitter.spec.ts | 20 ++++++++++++---- src/sync/submitters/eventsSubmitter.ts | 22 ++++++++--------- .../submitters/impressionCountsSubmitter.ts | 24 ++++++++++--------- src/sync/submitters/impressionsSubmitter.ts | 22 ++++++++--------- src/sync/submitters/submitterManager.ts | 13 +++++----- src/sync/submitters/telemetrySubmitter.ts | 4 ++-- 6 files changed, 57 insertions(+), 48 deletions(-) diff --git a/src/sync/submitters/__tests__/eventsSubmitter.spec.ts b/src/sync/submitters/__tests__/eventsSubmitter.spec.ts index a17ec656..16b26bc1 100644 --- a/src/sync/submitters/__tests__/eventsSubmitter.spec.ts +++ b/src/sync/submitters/__tests__/eventsSubmitter.spec.ts @@ -6,19 +6,28 @@ import { loggerMock } from '../../../logger/__tests__/sdkLogger.mock'; describe('Events submitter', () => { let __onFullQueueCb: () => void; - const postEventsBulkMock = jest.fn(); const eventsCacheMock = { isEmpty: jest.fn(() => true), setOnFullQueueCb: jest.fn(function (onFullQueueCb) { __onFullQueueCb = onFullQueueCb; }) }; + const params = { + settings: { + log: loggerMock, + scheduler: { eventsPushRate: 30000 }, + startup: { eventsFirstPushWindow: 0 } + }, + splitApi: { postEventsBulkMock: jest.fn() }, + storage: { events: eventsCacheMock } + }; beforeEach(() => { eventsCacheMock.isEmpty.mockClear(); }); test('with eventsFirstPushWindow', async () => { - const eventsFirstPushWindow = 20; // @ts-ignore - const eventsSubmitter = eventsSubmitterFactory(loggerMock, postEventsBulkMock, eventsCacheMock, 30000, eventsFirstPushWindow); + const eventsFirstPushWindow = 20; + params.settings.startup.eventsFirstPushWindow = eventsFirstPushWindow; // @ts-ignore + const eventsSubmitter = eventsSubmitterFactory(params); eventsSubmitter.start(); expect(eventsSubmitter.isRunning()).toEqual(true); // Submitter should be flagged as running @@ -40,8 +49,9 @@ describe('Events submitter', () => { }); test('without eventsFirstPushWindow', async () => { - // @ts-ignore - const eventsSubmitter = eventsSubmitterFactory(loggerMock, postEventsBulkMock, eventsCacheMock, 30000); + const eventsFirstPushWindow = 0; + params.settings.startup.eventsFirstPushWindow = eventsFirstPushWindow; // @ts-ignore + const eventsSubmitter = eventsSubmitterFactory(params); eventsSubmitter.start(); expect(eventsSubmitter.isRunning()).toEqual(true); // Submitter should be flagged as running diff --git a/src/sync/submitters/eventsSubmitter.ts b/src/sync/submitters/eventsSubmitter.ts index cbf36492..eb4f5da9 100644 --- a/src/sync/submitters/eventsSubmitter.ts +++ b/src/sync/submitters/eventsSubmitter.ts @@ -1,24 +1,22 @@ -import { IEventsCacheSync } from '../../storages/types'; -import { IPostEventsBulk } from '../../services/types'; import { submitterFactory } from './submitter'; -import { ILogger } from '../../logger/types'; import { SUBMITTERS_PUSH_FULL_QUEUE } from '../../logger/constants'; +import { ISdkFactoryContextSync } from '../../sdkFactory/types'; const DATA_NAME = 'events'; /** * Submitter that periodically posts tracked events */ -export function eventsSubmitterFactory( - log: ILogger, - postEventsBulk: IPostEventsBulk, - eventsCache: IEventsCacheSync, - eventsPushRate: number, - eventsFirstPushWindow: number, -) { +export function eventsSubmitterFactory(params: ISdkFactoryContextSync) { + + const { + settings: { log, scheduler: { eventsPushRate }, startup: { eventsFirstPushWindow } }, + splitApi: { postEventsBulk }, + storage: { events }, + } = params; // don't retry events. - const syncTask = submitterFactory(log, postEventsBulk, eventsCache, eventsPushRate, DATA_NAME); + const syncTask = submitterFactory(log, postEventsBulk, events, eventsPushRate, DATA_NAME); // Set a timer for the first push window of events. if (eventsFirstPushWindow > 0) { @@ -41,7 +39,7 @@ export function eventsSubmitterFactory( } // register events submitter to be executed when events cache is full - eventsCache.setOnFullQueueCb(() => { + events.setOnFullQueueCb(() => { if (syncTask.isRunning()) { log.info(SUBMITTERS_PUSH_FULL_QUEUE, [DATA_NAME]); syncTask.execute(); diff --git a/src/sync/submitters/impressionCountsSubmitter.ts b/src/sync/submitters/impressionCountsSubmitter.ts index 78fc6588..48131021 100644 --- a/src/sync/submitters/impressionCountsSubmitter.ts +++ b/src/sync/submitters/impressionCountsSubmitter.ts @@ -1,8 +1,6 @@ -import { IPostTestImpressionsCount } from '../../services/types'; -import { IImpressionCountsCacheSync } from '../../storages/types'; +import { ISdkFactoryContextSync } from '../../sdkFactory/types'; import { submitterFactory } from './submitter'; import { ImpressionCountsPayload } from './types'; -import { ILogger } from '../../logger/types'; /** * Converts `impressionCounts` data from cache into request payload. @@ -33,12 +31,16 @@ const IMPRESSIONS_COUNT_RATE = 1800000; // 30 minutes /** * Submitter that periodically posts impression counts */ -export function impressionCountsSubmitterFactory( - log: ILogger, - postTestImpressionsCount: IPostTestImpressionsCount, - impressionCountsCache: IImpressionCountsCacheSync, -) { - - // retry impressions counts only once. - return submitterFactory(log, postTestImpressionsCount, impressionCountsCache, IMPRESSIONS_COUNT_RATE, 'impression counts', fromImpressionCountsCollector, 1); +export function impressionCountsSubmitterFactory(params: ISdkFactoryContextSync) { + + const { + settings: { log }, + splitApi: { postTestImpressionsCount }, + storage: { impressionCounts } + } = params; + + if (impressionCounts) { + // retry impressions counts only once. + return submitterFactory(log, postTestImpressionsCount, impressionCounts, IMPRESSIONS_COUNT_RATE, 'impression counts', fromImpressionCountsCollector, 1); + } } diff --git a/src/sync/submitters/impressionsSubmitter.ts b/src/sync/submitters/impressionsSubmitter.ts index 3a01f6f2..e54b5f1f 100644 --- a/src/sync/submitters/impressionsSubmitter.ts +++ b/src/sync/submitters/impressionsSubmitter.ts @@ -1,11 +1,9 @@ import { groupBy, forOwn } from '../../utils/lang'; -import { IPostTestImpressionsBulk } from '../../services/types'; -import { IImpressionsCacheSync } from '../../storages/types'; import { ImpressionDTO } from '../../types'; import { submitterFactory } from './submitter'; import { ImpressionsPayload } from './types'; -import { ILogger } from '../../logger/types'; import { SUBMITTERS_PUSH_FULL_QUEUE } from '../../logger/constants'; +import { ISdkFactoryContextSync } from '../../sdkFactory/types'; const DATA_NAME = 'impressions'; @@ -42,19 +40,19 @@ export function fromImpressionsCollector(sendLabels: boolean, data: ImpressionDT /** * Submitter that periodically posts impressions data */ -export function impressionsSubmitterFactory( - log: ILogger, - postTestImpressionsBulk: IPostTestImpressionsBulk, - impressionsCache: IImpressionsCacheSync, - impressionsRefreshRate: number, - sendLabels = false, -) { +export function impressionsSubmitterFactory(params: ISdkFactoryContextSync) { + + const { + settings: { log, scheduler: { impressionsRefreshRate }, core: { labelsEnabled } }, + splitApi: { postTestImpressionsBulk }, + storage: { impressions } + } = params; // retry impressions only once. - const syncTask = submitterFactory(log, postTestImpressionsBulk, impressionsCache, impressionsRefreshRate, DATA_NAME, fromImpressionsCollector.bind(undefined, sendLabels), 1); + const syncTask = submitterFactory(log, postTestImpressionsBulk, impressions, impressionsRefreshRate, DATA_NAME, fromImpressionsCollector.bind(undefined, labelsEnabled), 1); // register impressions submitter to be executed when impressions cache is full - impressionsCache.setOnFullQueueCb(() => { + impressions.setOnFullQueueCb(() => { if (syncTask.isRunning()) { log.info(SUBMITTERS_PUSH_FULL_QUEUE, [DATA_NAME]); syncTask.execute(); diff --git a/src/sync/submitters/submitterManager.ts b/src/sync/submitters/submitterManager.ts index fc97f11a..4de02ec2 100644 --- a/src/sync/submitters/submitterManager.ts +++ b/src/sync/submitters/submitterManager.ts @@ -7,13 +7,14 @@ import { ISdkFactoryContextSync } from '../../sdkFactory/types'; export function submitterManagerFactory(params: ISdkFactoryContextSync) { - const { settings, storage, splitApi } = params; - const log = settings.log; const submitters = [ - impressionsSubmitterFactory(log, splitApi.postTestImpressionsBulk, storage.impressions, settings.scheduler.impressionsRefreshRate, settings.core.labelsEnabled), - eventsSubmitterFactory(log, splitApi.postEventsBulk, storage.events, settings.scheduler.eventsPushRate, settings.startup.eventsFirstPushWindow) + impressionsSubmitterFactory(params), + eventsSubmitterFactory(params), + telemetrySubmitterFactory(params) ]; - if (storage.impressionCounts) submitters.push(impressionCountsSubmitterFactory(log, splitApi.postTestImpressionsCount, storage.impressionCounts)); - if (storage.telemetry) submitters.push(telemetrySubmitterFactory(params)); + + const impressionCountsSubmitter = impressionCountsSubmitterFactory(params); + if (impressionCountsSubmitter) submitters.push(impressionCountsSubmitter); + return syncTaskComposite(submitters); } diff --git a/src/sync/submitters/telemetrySubmitter.ts b/src/sync/submitters/telemetrySubmitter.ts index 593cbbfc..3b052a13 100644 --- a/src/sync/submitters/telemetrySubmitter.ts +++ b/src/sync/submitters/telemetrySubmitter.ts @@ -6,8 +6,8 @@ import { SDK_READY, SDK_READY_FROM_CACHE } from '../../readiness/constants'; import { ISettings } from '../../types'; import { base } from '../../utils/settingsValidation'; import { usedKeysMap } from '../../utils/inputValidation/apiKey'; -import { ISyncManagerFactoryParams } from '../types'; import { timer } from '../../utils/timeTracker/timer'; +import { ISdkFactoryContextSync } from '../../sdkFactory/types'; /** * Converts data from telemetry cache into /metrics/usage request payload. @@ -117,7 +117,7 @@ export function telemetryCacheConfigAdapter(settings: ISettings, telemetryCache: /** * Submitter that periodically posts telemetry data */ -export function telemetrySubmitterFactory(params: ISyncManagerFactoryParams) { +export function telemetrySubmitterFactory(params: ISdkFactoryContextSync) { const { settings, settings: { log, scheduler: { telemetryRefreshRate } }, storage, splitApi, platform: { now }, readiness } = params; const startTime = timer(now || Date.now); From 7c12d3c52911aaa4ee4eaf8e8f2b708e9fff4f6c Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Wed, 4 May 2022 14:21:58 -0300 Subject: [PATCH 3/4] fix interface --- package-lock.json | 2 +- package.json | 2 +- src/sdkFactory/index.ts | 2 +- src/sdkFactory/types.ts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index f4a208a3..73687c88 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@splitsoftware/splitio-commons", - "version": "1.3.2-rc.0", + "version": "1.3.2-rc.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index e9861bed..987ecb67 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@splitsoftware/splitio-commons", - "version": "1.3.2-rc.0", + "version": "1.3.2-rc.1", "description": "Split Javascript SDK common components", "main": "cjs/index.js", "module": "esm/index.js", diff --git a/src/sdkFactory/index.ts b/src/sdkFactory/index.ts index bb5070d0..9bba6f95 100644 --- a/src/sdkFactory/index.ts +++ b/src/sdkFactory/index.ts @@ -69,7 +69,7 @@ export function sdkFactory(params: ISdkFactoryParams): SplitIO.ICsSDK | SplitIO. const telemetryTracker = telemetryTrackerFactory(storage.telemetry, platform.now); // splitApi is used by SyncManager and Browser signal listener - const splitApi = splitApiFactory && splitApiFactory(settings, platform); + const splitApi = splitApiFactory && splitApiFactory(settings, platform, telemetryTracker); const ctx: ISdkFactoryContext = { splitApi, eventTracker, impressionsTracker, telemetryTracker, sdkReadinessManager, readiness, settings, storage, platform }; diff --git a/src/sdkFactory/types.ts b/src/sdkFactory/types.ts index 9d0700ef..f041c863 100644 --- a/src/sdkFactory/types.ts +++ b/src/sdkFactory/types.ts @@ -64,7 +64,7 @@ export interface ISdkFactoryParams { // Factory of Split Api (HTTP Client Service). // It is not required when providing an asynchronous storage or offline SyncManager - splitApiFactory?: (settings: ISettings, platform: IPlatform) => ISplitApi, + splitApiFactory?: (settings: ISettings, platform: IPlatform, telemetryTracker: ITelemetryTracker) => ISplitApi, // SyncManager factory. // Not required when providing an asynchronous storage (consumer mode), but required in standalone mode to avoid SDK timeout. From 0fc8fee5ec5a8c8b6c0c4c358659773d3c2c0ec1 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Wed, 4 May 2022 17:44:26 -0300 Subject: [PATCH 4/4] update unit test to avoid flakiness --- src/storages/inRedis/__tests__/SegmentsCacheInRedis.spec.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/storages/inRedis/__tests__/SegmentsCacheInRedis.spec.ts b/src/storages/inRedis/__tests__/SegmentsCacheInRedis.spec.ts index e230fbc0..15d81e6b 100644 --- a/src/storages/inRedis/__tests__/SegmentsCacheInRedis.spec.ts +++ b/src/storages/inRedis/__tests__/SegmentsCacheInRedis.spec.ts @@ -36,6 +36,7 @@ describe('SEGMENTS CACHE IN REDIS', () => { expect(await cache.isInSegment('mocked-segment', 'd')).toBe(true); expect(await cache.isInSegment('mocked-segment', 'e')).toBe(true); + await cache.clear(); await connection.quit(); }); @@ -53,6 +54,7 @@ describe('SEGMENTS CACHE IN REDIS', () => { ['s1', 's2', 's3', 's4'].forEach(s => expect(segments.indexOf(s) !== -1).toBe(true)); + await cache.clear(); await connection.quit(); });