Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
6 changes: 5 additions & 1 deletion src/storages/AbstractSplitsCacheSync.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ISplitsCacheSync } from './types';
import { ISplitsCacheSync, IStorageSync } from './types';
import { IRBSegment, ISplit } from '../dtos/types';
import { objectAssign } from '../utils/lang/objectAssign';
import { IN_SEGMENT, IN_LARGE_SEGMENT } from '../utils/constants';
Expand Down Expand Up @@ -88,3 +88,7 @@ export function usesSegments(ruleEntity: ISplit | IRBSegment) {

return false;
}

export function usesSegmentsSync(storage: Pick<IStorageSync, 'splits' | 'rbSegments'>) {
return storage.splits.usesSegments() || storage.rbSegments.usesSegments();
}
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,9 @@ test('SPLITS CACHE / LocalStorage / flag set cache tests', () => {
], [], -1);
cache.addSplit(featureFlagWithEmptyFS);

// Adding an existing FF should not affect the cache
cache.update([featureFlagTwo], [], -1);

expect(cache.getNamesByFlagSets(['o'])).toEqual([new Set(['ff_one', 'ff_two'])]);
expect(cache.getNamesByFlagSets(['n'])).toEqual([new Set(['ff_one'])]);
expect(cache.getNamesByFlagSets(['e'])).toEqual([new Set(['ff_one', 'ff_three'])]);
Expand Down
3 changes: 3 additions & 0 deletions src/storages/inMemory/__tests__/SplitsCacheInMemory.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,9 @@ test('SPLITS CACHE / In Memory / flag set cache tests', () => {
], [], -1);
cache.addSplit(featureFlagWithEmptyFS);

// Adding an existing FF should not affect the cache
cache.update([featureFlagTwo], [], -1);

expect(cache.getNamesByFlagSets(['o'])).toEqual([new Set(['ff_one', 'ff_two'])]);
expect(cache.getNamesByFlagSets(['n'])).toEqual([new Set(['ff_one'])]);
expect(cache.getNamesByFlagSets(['e'])).toEqual([new Set(['ff_one', 'ff_three'])]);
Expand Down
9 changes: 5 additions & 4 deletions src/sync/polling/pollingManagerCS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ 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 { ISdkFactoryContextSync } from '../../sdkFactory/types';
import { usesSegmentsSync } from '../../storages/AbstractSplitsCacheSync';

/**
* Expose start / stop mechanism for polling data from services.
Expand Down Expand Up @@ -43,7 +44,7 @@ export function pollingManagerCSFactory(
// smart pausing
readiness.splits.on(SDK_SPLITS_ARRIVED, () => {
if (!splitsSyncTask.isRunning()) return; // noop if not doing polling
const usingSegments = storage.splits.usesSegments() || storage.rbSegments.usesSegments();
const usingSegments = usesSegmentsSync(storage);
if (usingSegments !== mySegmentsSyncTask.isRunning()) {
log.info(POLLING_SMART_PAUSING, [usingSegments ? 'ON' : 'OFF']);
if (usingSegments) {
Expand All @@ -59,9 +60,9 @@ export function pollingManagerCSFactory(

// smart ready
function smartReady() {
if (!readiness.isReady() && !storage.splits.usesSegments() && !storage.rbSegments.usesSegments()) readiness.segments.emit(SDK_SEGMENTS_ARRIVED);
if (!readiness.isReady() && !usesSegmentsSync(storage)) readiness.segments.emit(SDK_SEGMENTS_ARRIVED);
}
if (!storage.splits.usesSegments() && !storage.rbSegments.usesSegments()) setTimeout(smartReady, 0);
if (!usesSegmentsSync(storage)) setTimeout(smartReady, 0);
else readiness.splits.once(SDK_SPLITS_ARRIVED, smartReady);

mySegmentsSyncTasks[matchingKey] = mySegmentsSyncTask;
Expand All @@ -77,7 +78,7 @@ export function pollingManagerCSFactory(
log.info(POLLING_START);

splitsSyncTask.start();
if (storage.splits.usesSegments() || storage.rbSegments.usesSegments()) startMySegmentsSyncTasks();
if (usesSegmentsSync(storage)) startMySegmentsSyncTasks();
},

// Stop periodic fetching (polling)
Expand Down
5 changes: 3 additions & 2 deletions src/sync/polling/updaters/mySegmentsUpdater.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { SYNC_MYSEGMENTS_FETCH_RETRY } from '../../../logger/constants';
import { MySegmentsData } from '../types';
import { IMembershipsResponse } from '../../../dtos/types';
import { MEMBERSHIPS_LS_UPDATE } from '../../streaming/constants';
import { usesSegmentsSync } from '../../../storages/AbstractSplitsCacheSync';

type IMySegmentsUpdater = (segmentsData?: MySegmentsData, noCache?: boolean, till?: number) => Promise<boolean>

Expand All @@ -27,7 +28,7 @@ export function mySegmentsUpdaterFactory(
matchingKey: string
): IMySegmentsUpdater {

const { splits, rbSegments, segments, largeSegments } = storage;
const { segments, largeSegments } = storage;
let readyOnAlreadyExistentState = true;
let startingUp = true;

Expand All @@ -51,7 +52,7 @@ export function mySegmentsUpdaterFactory(
}

// Notify update if required
if ((splits.usesSegments() || rbSegments.usesSegments()) && (shouldNotifyUpdate || readyOnAlreadyExistentState)) {
if (usesSegmentsSync(storage) && (shouldNotifyUpdate || readyOnAlreadyExistentState)) {
readyOnAlreadyExistentState = false;
segmentsEventEmitter.emit(SDK_SEGMENTS_ARRIVED);
}
Expand Down
5 changes: 3 additions & 2 deletions src/sync/syncManagerOnline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { isConsentGranted } from '../consent';
import { POLLING, STREAMING, SYNC_MODE_UPDATE } from '../utils/constants';
import { ISdkFactoryContextSync } from '../sdkFactory/types';
import { SDK_SPLITS_CACHE_LOADED } from '../readiness/constants';
import { usesSegmentsSync } from '../storages/AbstractSplitsCacheSync';

/**
* Online SyncManager factory.
Expand Down Expand Up @@ -155,14 +156,14 @@ export function syncManagerOnlineFactory(
if (pushManager) {
if (pollingManager.isRunning()) {
// if doing polling, we must start the periodic fetch of data
if (storage.splits.usesSegments() || storage.rbSegments.usesSegments()) mySegmentsSyncTask.start();
if (usesSegmentsSync(storage)) mySegmentsSyncTask.start();
} else {
// if not polling, we must execute the sync task for the initial fetch
// of segments since `syncAll` was already executed when starting the main client
mySegmentsSyncTask.execute();
}
} else {
if (storage.splits.usesSegments() || storage.rbSegments.usesSegments()) mySegmentsSyncTask.start();
if (usesSegmentsSync(storage)) mySegmentsSyncTask.start();
}
} else {
if (!readinessManager.isReady()) mySegmentsSyncTask.execute();
Expand Down
38 changes: 24 additions & 14 deletions types/splitio.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,17 @@ interface ISharedSettings {
*
* @example
* ```
* const getHeaderOverrides = (context) => {
* return {
* 'Authorization': context.headers['Authorization'] + ', other-value',
* 'custom-header': 'custom-value'
* };
* };
* const factory = SplitFactory({
* ...
* sync: {
* getHeaderOverrides(context) {
* return {
* 'Authorization': context.headers['Authorization'] + ', other-value',
* 'custom-header': 'custom-value'
* };
* }
* }
* });
* ```
*/
getHeaderOverrides?: (context: { headers: Record<string, string> }) => Record<string, string>;
Expand Down Expand Up @@ -952,7 +957,7 @@ declare namespace SplitIO {
*/
prefix?: string;
/**
* Number of days before cached data expires if it was not updated. If cache expires, it is cleared on initialization.
* Number of days before cached data expires if it was not successfully synchronized (i.e., last SDK_READY or SDK_UPDATE event emitted). If cache expires, it is cleared on initialization.
*
* @defaultValue `10`
*/
Expand Down Expand Up @@ -1292,7 +1297,7 @@ declare namespace SplitIO {
*/
prefix?: string;
/**
* Optional settings for the 'LOCALSTORAGE' storage type. It specifies the number of days before cached data expires if it was not updated. If cache expires, it is cleared on initialization.
* Optional settings for the 'LOCALSTORAGE' storage type. It specifies the number of days before cached data expires if it was not successfully synchronized (i.e., last SDK_READY or SDK_UPDATE event emitted). If cache expires, it is cleared on initialization.
*
* @defaultValue `10`
*/
Expand Down Expand Up @@ -1350,12 +1355,17 @@ declare namespace SplitIO {
*
* @example
* ```
* const getHeaderOverrides = (context) => {
* return {
* 'Authorization': context.headers['Authorization'] + ', other-value',
* 'custom-header': 'custom-value'
* };
* };
* const factory = SplitFactory({
* ...
* sync: {
* getHeaderOverrides(context) {
* return {
* 'Authorization': context.headers['Authorization'] + ', other-value',
* 'custom-header': 'custom-value'
* };
* }
* }
* });
* ```
*/
getHeaderOverrides?: (context: { headers: Record<string, string> }) => Record<string, string>;
Expand Down