@@ -9,8 +9,10 @@ import { SYNC_SPLITS_FETCH, SYNC_SPLITS_UPDATE, SYNC_RBS_UPDATE, SYNC_SPLITS_FET
99import { startsWith } from '../../../utils/lang' ;
1010import { IN_RULE_BASED_SEGMENT , IN_SEGMENT } from '../../../utils/constants' ;
1111import { setToArray } from '../../../utils/lang/sets' ;
12+ import { SPLIT_UPDATE } from '../../streaming/constants' ;
1213
13- type ISplitChangesUpdater = ( noCache ?: boolean , till ?: number , splitUpdateNotification ?: { payload : ISplit | IRBSegment , changeNumber : number } ) => Promise < boolean >
14+ export type InstantUpdate = { payload : ISplit | IRBSegment , changeNumber : number , type : string } ;
15+ type SplitChangesUpdater = ( noCache ?: boolean , till ?: number , instantUpdate ?: InstantUpdate ) => Promise < boolean >
1416
1517// Checks that all registered segments have been fetched (changeNumber !== -1 for every segment).
1618// Returns a promise that could be rejected.
@@ -27,8 +29,9 @@ function checkAllSegmentsExist(segments: ISegmentsCacheBase): Promise<boolean> {
2729 * Collect segments from a raw split definition.
2830 * Exported for testing purposes.
2931 */
30- export function parseSegments ( { conditions } : ISplit | IRBSegment , matcherType : typeof IN_SEGMENT | typeof IN_RULE_BASED_SEGMENT = IN_SEGMENT ) : Set < string > {
31- let segments = new Set < string > ( ) ;
32+ export function parseSegments ( ruleEntity : ISplit | IRBSegment , matcherType : typeof IN_SEGMENT | typeof IN_RULE_BASED_SEGMENT = IN_SEGMENT ) : Set < string > {
33+ const { conditions, excluded } = ruleEntity as IRBSegment ;
34+ const segments = new Set < string > ( excluded && excluded . segments ) ;
3235
3336 for ( let i = 0 ; i < conditions . length ; i ++ ) {
3437 const matchers = conditions [ i ] . matcherGroup . matchers ;
@@ -67,26 +70,22 @@ function matchFilters(featureFlag: ISplit, filters: ISplitFiltersValidation) {
6770 return matchNames || matchPrefix ;
6871}
6972
70- function isFF ( ruleBasedEntity : IRBSegment | ISplit ) : ruleBasedEntity is ISplit {
71- return ( ruleBasedEntity as ISplit ) . defaultTreatment !== undefined ;
72- }
73-
7473/**
7574 * Given the list of splits from /splitChanges endpoint, it returns the mutations,
7675 * i.e., an object with added splits, removed splits and used segments.
7776 * Exported for testing purposes.
7877 */
7978export function computeMutation < T extends ISplit | IRBSegment > ( rules : Array < T > , segments : Set < string > , filters ?: ISplitFiltersValidation ) : ISplitMutations < T > {
8079
81- return rules . reduce ( ( accum , ruleBasedEntity ) => {
82- if ( ruleBasedEntity . status === 'ACTIVE' && ( ! filters || matchFilters ( ruleBasedEntity as ISplit , filters ) ) ) {
83- accum . added . push ( ruleBasedEntity ) ;
80+ return rules . reduce ( ( accum , ruleEntity ) => {
81+ if ( ruleEntity . status === 'ACTIVE' && ( ! filters || matchFilters ( ruleEntity as ISplit , filters ) ) ) {
82+ accum . added . push ( ruleEntity ) ;
8483
85- parseSegments ( ruleBasedEntity ) . forEach ( ( segmentName : string ) => {
84+ parseSegments ( ruleEntity ) . forEach ( ( segmentName : string ) => {
8685 segments . add ( segmentName ) ;
8786 } ) ;
8887 } else {
89- accum . removed . push ( ruleBasedEntity ) ;
88+ accum . removed . push ( ruleEntity ) ;
9089 }
9190
9291 return accum ;
@@ -116,7 +115,7 @@ export function splitChangesUpdaterFactory(
116115 requestTimeoutBeforeReady : number = 0 ,
117116 retriesOnFailureBeforeReady : number = 0 ,
118117 isClientSide ?: boolean
119- ) : ISplitChangesUpdater {
118+ ) : SplitChangesUpdater {
120119 const { splits, rbSegments, segments } = storage ;
121120
122121 let startingUp = true ;
@@ -134,7 +133,7 @@ export function splitChangesUpdaterFactory(
134133 * @param noCache - true to revalidate data to fetch
135134 * @param till - query param to bypass CDN requests
136135 */
137- return function splitChangesUpdater ( noCache ?: boolean , till ?: number , updateNotification ?: { payload : ISplit | IRBSegment , changeNumber : number } ) {
136+ return function splitChangesUpdater ( noCache ?: boolean , till ?: number , instantUpdate ?: InstantUpdate ) {
138137
139138 /**
140139 * @param since - current changeNumber at splitsCache
@@ -144,15 +143,15 @@ export function splitChangesUpdaterFactory(
144143 const [ since , rbSince ] = sinces ;
145144 log . debug ( SYNC_SPLITS_FETCH , sinces ) ;
146145 const fetcherPromise = Promise . resolve (
147- updateNotification ?
148- isFF ( updateNotification . payload ) ?
146+ instantUpdate ?
147+ instantUpdate . type === SPLIT_UPDATE ?
149148 // IFFU edge case: a change to a flag that adds an IN_RULE_BASED_SEGMENT matcher that is not present yet
150- Promise . resolve ( rbSegments . contains ( parseSegments ( updateNotification . payload , IN_RULE_BASED_SEGMENT ) ) ) . then ( ( contains ) => {
149+ Promise . resolve ( rbSegments . contains ( parseSegments ( instantUpdate . payload , IN_RULE_BASED_SEGMENT ) ) ) . then ( ( contains ) => {
151150 return contains ?
152- { ff : { d : [ updateNotification . payload as ISplit ] , t : updateNotification . changeNumber } } :
151+ { ff : { d : [ instantUpdate . payload as ISplit ] , t : instantUpdate . changeNumber } } :
153152 splitChangesFetcher ( since , noCache , till , rbSince , _promiseDecorator ) ;
154153 } ) :
155- { rbs : { d : [ updateNotification . payload as IRBSegment ] , t : updateNotification . changeNumber } } :
154+ { rbs : { d : [ instantUpdate . payload as IRBSegment ] , t : instantUpdate . changeNumber } } :
156155 splitChangesFetcher ( since , noCache , till , rbSince , _promiseDecorator )
157156 )
158157 . then ( ( splitChanges : ISplitChangesResponse ) => {
@@ -180,14 +179,8 @@ export function splitChangesUpdaterFactory(
180179 ] ) . then ( ( [ ffChanged , rbsChanged ] ) => {
181180 if ( splitsEventEmitter ) {
182181 // To emit SDK_SPLITS_ARRIVED for server-side SDK, we must check that all registered segments have been fetched
183- return Promise . resolve ( ! splitsEventEmitter . splitsArrived ||
184- (
185- ( ! splitChanges . ff || since !== splitChanges . ff . t ) &&
186- ( ! splitChanges . rbs || rbSince !== splitChanges . rbs . t ) &&
187- ( ffChanged || rbsChanged ) &&
188- ( isClientSide || checkAllSegmentsExist ( segments ) )
189- )
190- )
182+ return Promise . resolve ( ! splitsEventEmitter . splitsArrived || ( ( ffChanged || rbsChanged ) && ( isClientSide || checkAllSegmentsExist ( segments ) ) ) )
183+ . catch ( ( ) => false /** noop. just to handle a possible `checkAllSegmentsExist` rejection, before emitting SDK event */ )
191184 . then ( emitSplitsArrivedEvent => {
192185 // emit SDK events
193186 if ( emitSplitsArrivedEvent ) splitsEventEmitter . emit ( SDK_SPLITS_ARRIVED ) ;
0 commit comments