1+ import { ISettings } from '../../../../types/splitio' ;
2+ import { ISplitChangesResponse } from '../../../dtos/types' ;
13import { IFetchSplitChanges , IResponse } from '../../../services/types' ;
4+ import { IStorageBase } from '../../../storages/types' ;
5+ import { FLAG_SPEC_VERSION } from '../../../utils/constants' ;
6+ import { base } from '../../../utils/settingsValidation' ;
27import { ISplitChangesFetcher } from './types' ;
38
9+ const PROXY_CHECK_INTERVAL_MILLIS_CS = 60 * 60 * 1000 ; // 1 hour in Client Side
10+ const PROXY_CHECK_INTERVAL_MILLIS_SS = 24 * PROXY_CHECK_INTERVAL_MILLIS_CS ; // 24 hours in Server Side
11+
12+ function sdkEndpointOverriden ( settings : ISettings ) {
13+ return settings . urls . sdk !== base . urls . sdk ;
14+ }
15+
416/**
517 * Factory of SplitChanges fetcher.
618 * SplitChanges fetcher is a wrapper around `splitChanges` API service that parses the response and handle errors.
719 */
8- export function splitChangesFetcherFactory ( fetchSplitChanges : IFetchSplitChanges ) : ISplitChangesFetcher {
20+ export function splitChangesFetcherFactory ( fetchSplitChanges : IFetchSplitChanges , settings : ISettings , storage : Pick < IStorageBase , 'splits' | 'rbSegments' > ) : ISplitChangesFetcher {
21+
22+ const PROXY_CHECK_INTERVAL_MILLIS = settings . core . key !== undefined ? PROXY_CHECK_INTERVAL_MILLIS_CS : PROXY_CHECK_INTERVAL_MILLIS_SS ;
23+ let _lastProxyCheckTimestamp : number | undefined ;
924
1025 return function splitChangesFetcher (
1126 since : number ,
@@ -14,12 +29,48 @@ export function splitChangesFetcherFactory(fetchSplitChanges: IFetchSplitChanges
1429 rbSince ?: number ,
1530 // Optional decorator for `fetchSplitChanges` promise, such as timeout or time tracker
1631 decorator ?: ( promise : Promise < IResponse > ) => Promise < IResponse >
17- ) {
32+ ) : Promise < ISplitChangesResponse > {
33+
34+ if ( _lastProxyCheckTimestamp && ( Date . now ( ) - _lastProxyCheckTimestamp ) > PROXY_CHECK_INTERVAL_MILLIS ) {
35+ settings . sync . flagSpecVersion = FLAG_SPEC_VERSION ;
36+ }
37+
38+ let splitsPromise = fetchSplitChanges ( since , noCache , till , rbSince )
39+ // Handle proxy errors with spec 1.3
40+ . catch ( ( err ) => {
41+ if ( err . statusCode === 400 && sdkEndpointOverriden ( settings ) && settings . sync . flagSpecVersion === FLAG_SPEC_VERSION ) {
42+ _lastProxyCheckTimestamp = Date . now ( ) ;
43+ settings . sync . flagSpecVersion = '1.2' ; // fallback to 1.2 spec
44+ return fetchSplitChanges ( since , noCache , till ) ; // retry request without rbSince
45+ }
46+ throw err ;
47+ } ) ;
1848
19- let splitsPromise = fetchSplitChanges ( since , noCache , till , rbSince ) ;
2049 if ( decorator ) splitsPromise = decorator ( splitsPromise ) ;
2150
22- return splitsPromise . then ( resp => resp . json ( ) ) ;
51+ return splitsPromise
52+ . then ( resp => resp . json ( ) )
53+ . then ( data => {
54+ // Using flag spec version 1.2
55+ if ( data . splits ) {
56+ return {
57+ ff : {
58+ d : data . splits ,
59+ s : data . since ,
60+ t : data . till
61+ }
62+ } ;
63+ }
64+
65+ // Proxy recovery
66+ if ( _lastProxyCheckTimestamp ) {
67+ _lastProxyCheckTimestamp = undefined ;
68+ return Promise . all ( [ storage . splits . clear ( ) , storage . rbSegments . clear ( ) ] )
69+ . then ( ( ) => splitChangesFetcher ( - 1 , undefined , undefined , - 1 ) ) ;
70+ }
71+
72+ return data ;
73+ } ) ;
2374 } ;
2475
2576}
0 commit comments