diff --git a/CHANGES.txt b/CHANGES.txt index e3c1e5d..4dbca39 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,6 @@ -1.0.0 (May XXX, 2025) +1.0.0 (May 28, 2025) + - Added support for synchronizing feature flags with rule-based segments. These segments determine membership at runtime by evaluating their configured rules against the user attributes provided to the SDK. + - Added support for synchronizing feature flags with prerequisites. This allows customers to define dependency conditions between flags, which are evaluated before any allowlists or targeting rules. - Added support for synchronizing SDK impressions with properties. - Added `sync.requestOptions.getHeaderOverrides` configuration option to enhance Synchronizer HTTP request Headers for Authorization Frameworks. - Updated @splitsoftware/splitio-commons package to version 2.3.0 and some transitive dependencies for vulnerability fixes and other improvements. diff --git a/e2e/synchronizer.test.ts b/e2e/synchronizer.test.ts index 4bab15a..37e3bc9 100644 --- a/e2e/synchronizer.test.ts +++ b/e2e/synchronizer.test.ts @@ -66,7 +66,7 @@ describe('Synchronizer e2e tests', () => { describe('Runs Synchronizer for the [FIRST] time, and', () => { beforeAll(async () => { - fetchMock.getOnce(SERVER_MOCK_URL + '/splitChanges?s=1.1&since=-1', { status: 200, body: responseMocks.splitChanges[0] }); + fetchMock.getOnce(SERVER_MOCK_URL + '/splitChanges?s=1.3&since=-1&rbSince=-1', { status: 200, body: responseMocks.splitChanges[0] }); fetchMock.getOnce(SERVER_MOCK_URL + '/segmentChanges/test_maldo?since=-1', { status: 200, body: responseMocks.segmentChanges[0] }); fetchMock.getOnce(SERVER_MOCK_URL + '/segmentChanges/ENDIOS_PEREZ?since=-1', { status: 200, body: responseMocks.segmentChanges[1] }); fetchMock.getOnce(SERVER_MOCK_URL + '/segmentChanges/Lucas_Segments_Tests?since=-1', { status: 200, body: responseMocks.segmentChanges[2] }); @@ -116,6 +116,14 @@ describe('Synchronizer e2e tests', () => { expect(itemsSetB.sort()).toEqual(['TEST_DOC', 'TEST_MATIAS']); expect(itemsInexistentSet).toEqual([]); }); + + test('saves 1 rule-based segment', async () => { + const ruleBasedSegments = await _redisWrapper.getKeysByPrefix(`${REDIS_PREFIX}.rbsegment.*`); + expect(ruleBasedSegments).toHaveLength(1); + + expect(await _redisWrapper.get(`${REDIS_PREFIX}.rbsegments.till`)).toBe('100'); + }); + }); describe('Runs SDK Consumer with DEBUG impressions mode, and', () => { @@ -144,7 +152,7 @@ describe('Synchronizer e2e tests', () => { describe('Runs Synchronizer a [SECOND] time and', () => { beforeAll(async () => { - fetchMock.getOnce(SERVER_MOCK_URL + '/splitChanges?s=1.1&since=1619720346271', { status: 200, body: responseMocks.splitChanges[2] }); + fetchMock.getOnce(SERVER_MOCK_URL + '/splitChanges?s=1.3&since=1619720346271&rbSince=100', { status: 200, body: responseMocks.splitChanges[2] }); fetchMock.getOnce(SERVER_MOCK_URL + '/segmentChanges/test_maldo?since=1589906133231', { status: 200, body: responseMocks.segmentChanges[3] }); fetchMock.getOnce(SERVER_MOCK_URL + '/segmentChanges/Lucas_Segments_Tests?since=1617053238061', { status: 200, body: responseMocks.segmentChanges[6] }); @@ -224,7 +232,7 @@ describe('Synchronizer e2e tests', () => { }); test('Run Synchronizer and check that data was popped from Redis and sent to Split BE', async () => { - fetchMock.getOnce(SERVER_MOCK_URL + '/splitChanges?s=1.1&since=1619720346272', { status: 200, body: responseMocks.splitChanges[3] }); + fetchMock.getOnce(SERVER_MOCK_URL + '/splitChanges?s=1.3&since=1619720346272&rbSince=100', { status: 200, body: responseMocks.splitChanges[3] }); fetchMock.getOnce(SERVER_MOCK_URL + '/segmentChanges/test_maldo?since=1589906133231', { status: 200, body: responseMocks.segmentChanges[3] }); fetchMock.getOnce(SERVER_MOCK_URL + '/segmentChanges/Lucas_Segments_Tests?since=1617053238061', { status: 200, body: responseMocks.segmentChanges[6] }); @@ -272,7 +280,7 @@ describe('Synchronizer e2e tests', () => { }); test('Run Synchronizer and check that data was popped from Redis and sent to Split BE', async () => { - fetchMock.getOnce(SERVER_MOCK_URL + '/splitChanges?s=1.1&since=1619720346272', { status: 200, body: responseMocks.splitChanges[3] }); + fetchMock.getOnce(SERVER_MOCK_URL + '/splitChanges?s=1.3&since=1619720346272&rbSince=100', { status: 200, body: responseMocks.splitChanges[3] }); fetchMock.getOnce(SERVER_MOCK_URL + '/segmentChanges/test_maldo?since=1589906133231', { status: 200, body: responseMocks.segmentChanges[3] }); fetchMock.getOnce(SERVER_MOCK_URL + '/segmentChanges/Lucas_Segments_Tests?since=1617053238061', { status: 200, body: responseMocks.segmentChanges[6] }); @@ -347,7 +355,7 @@ describe('Synchronizer e2e tests - OPTIMIZED impressions mode & Flag Sets filter describe('Synchronizer runs the first time', () => { beforeAll(async () => { - fetchMock.getOnce(SERVER_MOCK_URL + '/splitChanges?s=1.1&since=-1&sets=set_b', { status: 200, body: responseMocks.splitChanges[0] }); + fetchMock.getOnce(SERVER_MOCK_URL + '/splitChanges?s=1.3&since=-1&rbSince=-1&sets=set_b', { status: 200, body: responseMocks.splitChanges[0] }); fetchMock.getOnce(SERVER_MOCK_URL + '/segmentChanges/test_maldo?since=-1', { status: 200, body: responseMocks.segmentChanges[0] }); fetchMock.getOnce(SERVER_MOCK_URL + '/segmentChanges/test_maldo?since=1589906133231', { status: 200, body: responseMocks.segmentChanges[3] }); @@ -402,7 +410,7 @@ describe('Synchronizer e2e tests - OPTIMIZED impressions mode & Flag Sets filter describe('Synchronizer runs a second time, and', () => { beforeAll(async () => { - fetchMock.getOnce(SERVER_MOCK_URL + '/splitChanges?s=1.1&since=1619720346271&sets=set_b', { status: 200, body: responseMocks.splitChanges[2] }); + fetchMock.getOnce(SERVER_MOCK_URL + '/splitChanges?s=1.3&since=1619720346271&rbSince=100&sets=set_b', { status: 200, body: responseMocks.splitChanges[2] }); fetchMock.getOnce(SERVER_MOCK_URL + '/segmentChanges/test_maldo?since=1589906133231', { status: 200, body: responseMocks.segmentChanges[3] }); await _synchronizer.execute(); @@ -460,7 +468,7 @@ describe('Synchronizer e2e tests - OPTIMIZED impressions mode & Flag Sets filter }, }); - fetchMock.getOnce(SERVER_MOCK_URL + '/splitChanges?s=1.1&since=1619720346272&sets=set_b', { status: 500 }); + fetchMock.getOnce(SERVER_MOCK_URL + '/splitChanges?s=1.3&since=1619720346272&rbSince=100&sets=set_b', { status: 500 }); fetchMock.getOnce(SERVER_MOCK_URL + '/segmentChanges/test_maldo?since=1589906133231', { status: 200, body: responseMocks.segmentChanges[3] }); expect(await synchronizer.execute()).toBe(false); @@ -477,7 +485,7 @@ describe('Synchronizer e2e tests - OPTIMIZED impressions mode & Flag Sets filter }, }); - fetchMock.getOnce(SERVER_MOCK_URL + '/splitChanges?s=1.1&since=-1&sets=set_b', { status: 500 }); + fetchMock.getOnce(SERVER_MOCK_URL + '/splitChanges?s=1.3&since=-1&rbSince=-1&sets=set_b', { status: 500 }); expect(await synchronizer.execute()).toBe(false); expect(keys.length).toBeGreaterThan(0); @@ -491,7 +499,7 @@ describe('Synchronizer - only Splits & Segments mode', () => { let executeImpressionsAndEventsCallSpy: jest.SpyInstance; beforeAll(async () => { - fetchMock.getOnce(SERVER_MOCK_URL + '/splitChanges?s=1.1&since=-1', { status: 200, body: responseMocks.splitChanges[0] }); + fetchMock.getOnce(SERVER_MOCK_URL + '/splitChanges?s=1.3&since=-1&rbSince=-1', { status: 200, body: responseMocks.splitChanges[0] }); fetchMock.getOnce(SERVER_MOCK_URL + '/segmentChanges/test_maldo?since=-1', { status: 200, body: responseMocks.segmentChanges[0] }); fetchMock.getOnce(SERVER_MOCK_URL + '/segmentChanges/Lucas_Segments_Tests?since=-1', { status: 200, body: responseMocks.segmentChanges[2] }); fetchMock.getOnce(SERVER_MOCK_URL + '/segmentChanges/test_maldo?since=1589906133231', { status: 200, body: responseMocks.segmentChanges[3] }); diff --git a/e2e/utils/responseMocks.json b/e2e/utils/responseMocks.json index f7e354d..33d51f7 100644 --- a/e2e/utils/responseMocks.json +++ b/e2e/utils/responseMocks.json @@ -1,692 +1,754 @@ { "splitChanges": [ { - "splits": [ - { - "trafficTypeName": "testTT", - "name": "MATIAS_TEST", - "trafficAllocation": 92, - "trafficAllocationSeed": 59120715, - "seed": -2094556730, - "status": "ACTIVE", - "killed": false, - "defaultTreatment": "off", - "changeNumber": 1619720346270, - "algo": 2, - "configurations": {}, - "sets": ["set_a"], - "conditions": [ - { - "conditionType": "ROLLOUT", - "matcherGroup": { - "combiner": "AND", - "matchers": [ - { - "keySelector": { - "trafficType": "account", - "attribute": "test" - }, - "matcherType": "MATCHES_STRING", - "negate": false, - "userDefinedSegmentMatcherData": null, - "whitelistMatcherData": null, - "unaryNumericMatcherData": null, - "betweenMatcherData": null, - "booleanMatcherData": null, - "dependencyMatcherData": null, - "stringMatcherData": "/matias/i" - } - ] - }, - "partitions": [ - { - "treatment": "on", - "size": 100 + "ff": { + "d": [ + { + "trafficTypeName": "testTT", + "name": "MATIAS_TEST", + "trafficAllocation": 92, + "trafficAllocationSeed": 59120715, + "seed": -2094556730, + "status": "ACTIVE", + "killed": false, + "defaultTreatment": "off", + "changeNumber": 1619720346270, + "algo": 2, + "configurations": {}, + "sets": [ + "set_a" + ], + "conditions": [ + { + "conditionType": "ROLLOUT", + "matcherGroup": { + "combiner": "AND", + "matchers": [ + { + "keySelector": { + "trafficType": "account", + "attribute": "test" + }, + "matcherType": "MATCHES_STRING", + "negate": false, + "userDefinedSegmentMatcherData": null, + "whitelistMatcherData": null, + "unaryNumericMatcherData": null, + "betweenMatcherData": null, + "booleanMatcherData": null, + "dependencyMatcherData": null, + "stringMatcherData": "/matias/i" + } + ] }, - { - "treatment": "off", - "size": 0 - } - ], - "label": "test matches /matias/i" - }, - { - "conditionType": "ROLLOUT", - "matcherGroup": { - "combiner": "AND", - "matchers": [ - { - "keySelector": { - "trafficType": "account", - "attribute": null - }, - "matcherType": "ALL_KEYS", - "negate": false, - "userDefinedSegmentMatcherData": null, - "whitelistMatcherData": null, - "unaryNumericMatcherData": null, - "betweenMatcherData": null, - "booleanMatcherData": null, - "dependencyMatcherData": null, - "stringMatcherData": null + "partitions": [ + { + "treatment": "on", + "size": 100 + }, + { + "treatment": "off", + "size": 0 } - ] + ], + "label": "test matches /matias/i" }, - "partitions": [ - { - "treatment": "on", - "size": 0 + { + "conditionType": "ROLLOUT", + "matcherGroup": { + "combiner": "AND", + "matchers": [ + { + "keySelector": { + "trafficType": "account", + "attribute": null + }, + "matcherType": "ALL_KEYS", + "negate": false, + "userDefinedSegmentMatcherData": null, + "whitelistMatcherData": null, + "unaryNumericMatcherData": null, + "betweenMatcherData": null, + "booleanMatcherData": null, + "dependencyMatcherData": null, + "stringMatcherData": null + } + ] }, - { - "treatment": "off", - "size": 100 - } - ], - "label": "default rule" - } - ] - }, - { - "trafficTypeName": "user", - "name": "TEST_MATIAS", - "trafficAllocation": 44, - "trafficAllocationSeed": -1207740278, - "seed": 203792729, - "status": "ACTIVE", - "killed": false, - "defaultTreatment": "off", - "changeNumber": 1619205925116, - "algo": 2, - "configurations": {}, - "sets": ["set_b"], - "conditions": [ - { - "conditionType": "WHITELIST", - "matcherGroup": { - "combiner": "AND", - "matchers": [ - { - "keySelector": null, - "matcherType": "IN_SEGMENT", - "negate": false, - "userDefinedSegmentMatcherData": { - "segmentName": "test_maldo" - }, - "whitelistMatcherData": null, - "unaryNumericMatcherData": null, - "betweenMatcherData": null, - "booleanMatcherData": null, - "dependencyMatcherData": null, - "stringMatcherData": null + "partitions": [ + { + "treatment": "on", + "size": 0 + }, + { + "treatment": "off", + "size": 100 } - ] - }, - "partitions": [ - { - "treatment": "on", - "size": 100 - } - ], - "label": "whitelisted segment" - }, - { - "conditionType": "ROLLOUT", - "matcherGroup": { - "combiner": "AND", - "matchers": [ - { - "keySelector": { - "trafficType": "user", - "attribute": null - }, - "matcherType": "ALL_KEYS", - "negate": false, - "userDefinedSegmentMatcherData": null, - "whitelistMatcherData": null, - "unaryNumericMatcherData": null, - "betweenMatcherData": null, - "booleanMatcherData": null, - "dependencyMatcherData": null, - "stringMatcherData": null + ], + "label": "default rule" + } + ] + }, + { + "trafficTypeName": "user", + "name": "TEST_MATIAS", + "trafficAllocation": 44, + "trafficAllocationSeed": -1207740278, + "seed": 203792729, + "status": "ACTIVE", + "killed": false, + "defaultTreatment": "off", + "changeNumber": 1619205925116, + "algo": 2, + "configurations": {}, + "sets": [ + "set_b" + ], + "conditions": [ + { + "conditionType": "WHITELIST", + "matcherGroup": { + "combiner": "AND", + "matchers": [ + { + "keySelector": null, + "matcherType": "IN_SEGMENT", + "negate": false, + "userDefinedSegmentMatcherData": { + "segmentName": "test_maldo" + }, + "whitelistMatcherData": null, + "unaryNumericMatcherData": null, + "betweenMatcherData": null, + "booleanMatcherData": null, + "dependencyMatcherData": null, + "stringMatcherData": null + } + ] + }, + "partitions": [ + { + "treatment": "on", + "size": 100 } - ] + ], + "label": "whitelisted segment" }, - "partitions": [ - { - "treatment": "on", - "size": 100 - }, - { - "treatment": "off", - "size": 0 - }, - { - "treatment": "PITY_MARTINEZ", - "size": 0 + { + "conditionType": "ROLLOUT", + "matcherGroup": { + "combiner": "AND", + "matchers": [ + { + "keySelector": { + "trafficType": "user", + "attribute": null + }, + "matcherType": "ALL_KEYS", + "negate": false, + "userDefinedSegmentMatcherData": null, + "whitelistMatcherData": null, + "unaryNumericMatcherData": null, + "betweenMatcherData": null, + "booleanMatcherData": null, + "dependencyMatcherData": null, + "stringMatcherData": null + } + ] }, - { - "treatment": "JUANFER_QUINTERO", - "size": 0 - }, - { - "treatment": "LUQUITAS_PRATTO", - "size": 0 - }, - { - "treatment": "ENZO_PEREZ", - "size": 0 - }, - { - "treatment": "REDO", - "size": 0 - } - ], - "label": "default rule" - } - ] - }, - { - "trafficTypeName": "user", - "name": "TEST_DOC", - "trafficAllocation": 100, - "trafficAllocationSeed": -1845986406, - "seed": 255141922, - "status": "ACTIVE", - "killed": false, - "defaultTreatment": "off", - "changeNumber": 1555536480284, - "algo": 2, - "configurations": { - "on": "{\"ojoijoii\":\"oijoijioj\",\"\":\"\"}" + "partitions": [ + { + "treatment": "on", + "size": 100 + }, + { + "treatment": "off", + "size": 0 + }, + { + "treatment": "PITY_MARTINEZ", + "size": 0 + }, + { + "treatment": "JUANFER_QUINTERO", + "size": 0 + }, + { + "treatment": "LUQUITAS_PRATTO", + "size": 0 + }, + { + "treatment": "ENZO_PEREZ", + "size": 0 + }, + { + "treatment": "REDO", + "size": 0 + } + ], + "label": "default rule" + } + ] }, - "sets": ["set_a", "set_b"], - "conditions": [ - { - "conditionType": "ROLLOUT", - "matcherGroup": { - "combiner": "AND", - "matchers": [ - { - "keySelector": { - "trafficType": "desded", - "attribute": null - }, - "matcherType": "ALL_KEYS", - "negate": false, - "userDefinedSegmentMatcherData": null, - "whitelistMatcherData": null, - "unaryNumericMatcherData": null, - "betweenMatcherData": null, - "booleanMatcherData": null, - "dependencyMatcherData": null, - "stringMatcherData": null + { + "trafficTypeName": "user", + "name": "TEST_DOC", + "trafficAllocation": 100, + "trafficAllocationSeed": -1845986406, + "seed": 255141922, + "status": "ACTIVE", + "killed": false, + "defaultTreatment": "off", + "changeNumber": 1555536480284, + "algo": 2, + "configurations": { + "on": "{\"ojoijoii\":\"oijoijioj\",\"\":\"\"}" + }, + "sets": [ + "set_a", + "set_b" + ], + "conditions": [ + { + "conditionType": "ROLLOUT", + "matcherGroup": { + "combiner": "AND", + "matchers": [ + { + "keySelector": { + "trafficType": "desded", + "attribute": null + }, + "matcherType": "ALL_KEYS", + "negate": false, + "userDefinedSegmentMatcherData": null, + "whitelistMatcherData": null, + "unaryNumericMatcherData": null, + "betweenMatcherData": null, + "booleanMatcherData": null, + "dependencyMatcherData": null, + "stringMatcherData": null + } + ] + }, + "partitions": [ + { + "treatment": "on", + "size": 0 + }, + { + "treatment": "off", + "size": 100 } - ] - }, - "partitions": [ - { - "treatment": "on", - "size": 0 + ], + "label": "default rule" + } + ] + }, + { + "trafficTypeName": "user", + "name": "Lucas_Split", + "trafficAllocation": 32, + "trafficAllocationSeed": 2048379668, + "seed": 871802730, + "status": "ACTIVE", + "killed": false, + "defaultTreatment": "v1", + "changeNumber": 1619205566698, + "algo": 2, + "configurations": {}, + "sets": [], + "conditions": [ + { + "conditionType": "WHITELIST", + "matcherGroup": { + "combiner": "AND", + "matchers": [ + { + "keySelector": null, + "matcherType": "IN_SEGMENT", + "negate": false, + "userDefinedSegmentMatcherData": { + "segmentName": "Lucas_Segments_Tests" + }, + "whitelistMatcherData": null, + "unaryNumericMatcherData": null, + "betweenMatcherData": null, + "booleanMatcherData": null, + "dependencyMatcherData": null, + "stringMatcherData": null + } + ] }, - { - "treatment": "off", - "size": 100 - } - ], - "label": "default rule" - } - ] - }, - { - "trafficTypeName": "user", - "name": "Lucas_Split", - "trafficAllocation": 32, - "trafficAllocationSeed": 2048379668, - "seed": 871802730, - "status": "ACTIVE", - "killed": false, - "defaultTreatment": "v1", - "changeNumber": 1619205566698, - "algo": 2, - "configurations": {}, - "sets": [], - "conditions": [ - { - "conditionType": "WHITELIST", - "matcherGroup": { - "combiner": "AND", - "matchers": [ - { - "keySelector": null, - "matcherType": "IN_SEGMENT", - "negate": false, - "userDefinedSegmentMatcherData": { - "segmentName": "Lucas_Segments_Tests" - }, - "whitelistMatcherData": null, - "unaryNumericMatcherData": null, - "betweenMatcherData": null, - "booleanMatcherData": null, - "dependencyMatcherData": null, - "stringMatcherData": null + "partitions": [ + { + "treatment": "on", + "size": 100 } - ] + ], + "label": "whitelisted segment" }, - "partitions": [ - { - "treatment": "on", - "size": 100 - } - ], - "label": "whitelisted segment" - }, - { - "conditionType": "ROLLOUT", - "matcherGroup": { - "combiner": "AND", - "matchers": [ - { - "keySelector": { - "trafficType": "user", - "attribute": null - }, - "matcherType": "IN_SEGMENT", - "negate": false, - "userDefinedSegmentMatcherData": { - "segmentName": "Lucas_Segments_Tests" - }, - "whitelistMatcherData": null, - "unaryNumericMatcherData": null, - "betweenMatcherData": null, - "booleanMatcherData": null, - "dependencyMatcherData": null, - "stringMatcherData": null + { + "conditionType": "ROLLOUT", + "matcherGroup": { + "combiner": "AND", + "matchers": [ + { + "keySelector": { + "trafficType": "user", + "attribute": null + }, + "matcherType": "IN_SEGMENT", + "negate": false, + "userDefinedSegmentMatcherData": { + "segmentName": "Lucas_Segments_Tests" + }, + "whitelistMatcherData": null, + "unaryNumericMatcherData": null, + "betweenMatcherData": null, + "booleanMatcherData": null, + "dependencyMatcherData": null, + "stringMatcherData": null + } + ] + }, + "partitions": [ + { + "treatment": "on", + "size": 0 + }, + { + "treatment": "off", + "size": 0 + }, + { + "treatment": "v1", + "size": 100 } - ] + ], + "label": "in segment Lucas_Segments_Tests" }, - "partitions": [ - { - "treatment": "on", - "size": 0 - }, - { - "treatment": "off", - "size": 0 + { + "conditionType": "ROLLOUT", + "matcherGroup": { + "combiner": "AND", + "matchers": [ + { + "keySelector": { + "trafficType": "user", + "attribute": null + }, + "matcherType": "ALL_KEYS", + "negate": false, + "userDefinedSegmentMatcherData": null, + "whitelistMatcherData": null, + "unaryNumericMatcherData": null, + "betweenMatcherData": null, + "booleanMatcherData": null, + "dependencyMatcherData": null, + "stringMatcherData": null + } + ] }, + "partitions": [ + { + "treatment": "on", + "size": 0 + }, + { + "treatment": "off", + "size": 100 + }, + { + "treatment": "v1", + "size": 0 + } + ], + "label": "default rule" + } + ] + } + ], + "s": -1, + "t": 1619720346271 + }, + "rbs": { + "s": -1, + "t": 100, + "d": [ + { + "changeNumber": 5, + "name": "test_rule_based_segment", + "status": "ACTIVE", + "trafficTypeName": "user", + "excluded": { + "keys": [ + "mauro@split.io", + "gaston@split.io" + ], + "segments": [ { - "treatment": "v1", - "size": 100 + "type": "standard", + "name": "test_maldo" } - ], - "label": "in segment Lucas_Segments_Tests" + ] }, - { - "conditionType": "ROLLOUT", - "matcherGroup": { - "combiner": "AND", - "matchers": [ - { - "keySelector": { - "trafficType": "user", - "attribute": null - }, - "matcherType": "ALL_KEYS", - "negate": false, - "userDefinedSegmentMatcherData": null, - "whitelistMatcherData": null, - "unaryNumericMatcherData": null, - "betweenMatcherData": null, - "booleanMatcherData": null, - "dependencyMatcherData": null, - "stringMatcherData": null - } - ] - }, - "partitions": [ - { - "treatment": "on", - "size": 0 - }, - { - "treatment": "off", - "size": 100 - }, - { - "treatment": "v1", - "size": 0 + "conditions": [ + { + "matcherGroup": { + "combiner": "AND", + "matchers": [ + { + "keySelector": { + "trafficType": "user" + }, + "matcherType": "ENDS_WITH", + "negate": false, + "whitelistMatcherData": { + "whitelist": [ + "@split.io" + ] + } + } + ] } - ], - "label": "default rule" - } - ] - } - ], - "since": -1, - "till": 1619720346271 + } + ] + } + ] + } }, { - "splits": [], - "since": 1619720346271, - "till": 1619720346271 + "ff": { + "d": [], + "s": 1619720346271, + "t": 1619720346271 + } }, { - "splits": [ - { - "trafficTypeName": "account", - "name": "TEST_RULO", - "trafficAllocation": 100, - "trafficAllocationSeed": -1845986406, - "seed": 255141922, - "status": "ACTIVE", - "killed": false, - "defaultTreatment": "off", - "changeNumber": 1555536480284, - "algo": 2, - "configurations": { - "on": "{\"ojoijoii\":\"oijoijioj\",\"\":\"\"}" - }, - "conditions": [ - { - "conditionType": "ROLLOUT", - "matcherGroup": { - "combiner": "AND", - "matchers": [ - { - "keySelector": { - "trafficType": "desded", - "attribute": null - }, - "matcherType": "ALL_KEYS", - "negate": false, - "userDefinedSegmentMatcherData": null, - "whitelistMatcherData": null, - "unaryNumericMatcherData": null, - "betweenMatcherData": null, - "booleanMatcherData": null, - "dependencyMatcherData": null, - "stringMatcherData": null - } - ] - }, - "partitions": [ - { - "treatment": "on", - "size": 0 + "ff": { + "d": [ + { + "trafficTypeName": "account", + "name": "TEST_RULO", + "trafficAllocation": 100, + "trafficAllocationSeed": -1845986406, + "seed": 255141922, + "status": "ACTIVE", + "killed": false, + "defaultTreatment": "off", + "changeNumber": 1555536480284, + "algo": 2, + "configurations": { + "on": "{\"ojoijoii\":\"oijoijioj\",\"\":\"\"}" + }, + "conditions": [ + { + "conditionType": "ROLLOUT", + "matcherGroup": { + "combiner": "AND", + "matchers": [ + { + "keySelector": { + "trafficType": "desded", + "attribute": null + }, + "matcherType": "ALL_KEYS", + "negate": false, + "userDefinedSegmentMatcherData": null, + "whitelistMatcherData": null, + "unaryNumericMatcherData": null, + "betweenMatcherData": null, + "booleanMatcherData": null, + "dependencyMatcherData": null, + "stringMatcherData": null + } + ] }, - { - "treatment": "off", - "size": 100 - } - ], - "label": "default rule" - } - ] - }, - { - "trafficTypeName": "account", - "name": "MATIAS_TEST", - "trafficAllocation": 92, - "trafficAllocationSeed": 59120715, - "seed": -2094556730, - "status": "ACTIVE", - "killed": false, - "defaultTreatment": "off", - "changeNumber": 1619720346272, - "algo": 2, - "configurations": {}, - "sets": ["set_c"], - "conditions": [ - { - "conditionType": "ROLLOUT", - "matcherGroup": { - "combiner": "AND", - "matchers": [ - { - "keySelector": { - "trafficType": "account", - "attribute": "test" - }, - "matcherType": "MATCHES_STRING", - "negate": false, - "userDefinedSegmentMatcherData": null, - "whitelistMatcherData": null, - "unaryNumericMatcherData": null, - "betweenMatcherData": null, - "booleanMatcherData": null, - "dependencyMatcherData": null, - "stringMatcherData": "/matias/i" + "partitions": [ + { + "treatment": "on", + "size": 0 + }, + { + "treatment": "off", + "size": 100 } - ] - }, - "partitions": [ - { - "treatment": "on", - "size": 100 + ], + "label": "default rule" + } + ] + }, + { + "trafficTypeName": "account", + "name": "MATIAS_TEST", + "trafficAllocation": 92, + "trafficAllocationSeed": 59120715, + "seed": -2094556730, + "status": "ACTIVE", + "killed": false, + "defaultTreatment": "off", + "changeNumber": 1619720346272, + "algo": 2, + "configurations": {}, + "sets": [ + "set_c" + ], + "conditions": [ + { + "conditionType": "ROLLOUT", + "matcherGroup": { + "combiner": "AND", + "matchers": [ + { + "keySelector": { + "trafficType": "account", + "attribute": "test" + }, + "matcherType": "MATCHES_STRING", + "negate": false, + "userDefinedSegmentMatcherData": null, + "whitelistMatcherData": null, + "unaryNumericMatcherData": null, + "betweenMatcherData": null, + "booleanMatcherData": null, + "dependencyMatcherData": null, + "stringMatcherData": "/matias/i" + } + ] }, - { - "treatment": "off", - "size": 0 - } - ], - "label": "test matches /matias/i" - }, - { - "conditionType": "ROLLOUT", - "matcherGroup": { - "combiner": "AND", - "matchers": [ - { - "keySelector": { - "trafficType": "account", - "attribute": null - }, - "matcherType": "ALL_KEYS", - "negate": false, - "userDefinedSegmentMatcherData": null, - "whitelistMatcherData": null, - "unaryNumericMatcherData": null, - "betweenMatcherData": null, - "booleanMatcherData": null, - "dependencyMatcherData": null, - "stringMatcherData": null + "partitions": [ + { + "treatment": "on", + "size": 100 + }, + { + "treatment": "off", + "size": 0 } - ] + ], + "label": "test matches /matias/i" }, - "partitions": [ - { - "treatment": "on", - "size": 0 + { + "conditionType": "ROLLOUT", + "matcherGroup": { + "combiner": "AND", + "matchers": [ + { + "keySelector": { + "trafficType": "account", + "attribute": null + }, + "matcherType": "ALL_KEYS", + "negate": false, + "userDefinedSegmentMatcherData": null, + "whitelistMatcherData": null, + "unaryNumericMatcherData": null, + "betweenMatcherData": null, + "booleanMatcherData": null, + "dependencyMatcherData": null, + "stringMatcherData": null + } + ] }, - { - "treatment": "off", - "size": 100 - } - ], - "label": "default rule" - } - ] - }, - { - "trafficTypeName": "user", - "name": "TEST_DOC", - "trafficAllocation": 100, - "trafficAllocationSeed": -1845986406, - "seed": 255141922, - "status": "ACTIVE", - "killed": false, - "defaultTreatment": "on", - "changeNumber": 1619720346272, - "algo": 2, - "configurations": { - "on": "{\"ojoijoii\":\"oijoijioj\",\"\":\"\"}" - }, - "conditions": [ - { - "conditionType": "ROLLOUT", - "matcherGroup": { - "combiner": "AND", - "matchers": [ - { - "keySelector": { - "trafficType": "desded", - "attribute": null - }, - "matcherType": "ALL_KEYS", - "negate": false, - "userDefinedSegmentMatcherData": null, - "whitelistMatcherData": null, - "unaryNumericMatcherData": null, - "betweenMatcherData": null, - "booleanMatcherData": null, - "dependencyMatcherData": null, - "stringMatcherData": null + "partitions": [ + { + "treatment": "on", + "size": 0 + }, + { + "treatment": "off", + "size": 100 } - ] - }, - "partitions": [ - { - "treatment": "on", - "size": 0 + ], + "label": "default rule" + } + ] + }, + { + "trafficTypeName": "user", + "name": "TEST_DOC", + "trafficAllocation": 100, + "trafficAllocationSeed": -1845986406, + "seed": 255141922, + "status": "ACTIVE", + "killed": false, + "defaultTreatment": "on", + "changeNumber": 1619720346272, + "algo": 2, + "configurations": { + "on": "{\"ojoijoii\":\"oijoijioj\",\"\":\"\"}" + }, + "conditions": [ + { + "conditionType": "ROLLOUT", + "matcherGroup": { + "combiner": "AND", + "matchers": [ + { + "keySelector": { + "trafficType": "desded", + "attribute": null + }, + "matcherType": "ALL_KEYS", + "negate": false, + "userDefinedSegmentMatcherData": null, + "whitelistMatcherData": null, + "unaryNumericMatcherData": null, + "betweenMatcherData": null, + "booleanMatcherData": null, + "dependencyMatcherData": null, + "stringMatcherData": null + } + ] }, - { - "treatment": "off", - "size": 100 - } - ], - "label": "default rule" - } - ] - }, - { - "trafficTypeName": "user", - "name": "Lucas_Split", - "trafficAllocation": 32, - "trafficAllocationSeed": 2048379668, - "seed": 871802730, - "status": "ARCHIVED", - "killed": false, - "defaultTreatment": "v1", - "changeNumber": 1619720346272, - "algo": 2, - "configurations": {}, - "conditions": [ - { - "conditionType": "WHITELIST", - "matcherGroup": { - "combiner": "AND", - "matchers": [ - { - "keySelector": null, - "matcherType": "IN_SEGMENT", - "negate": false, - "userDefinedSegmentMatcherData": { - "segmentName": "Lucas_Segments_Tests" - }, - "whitelistMatcherData": null, - "unaryNumericMatcherData": null, - "betweenMatcherData": null, - "booleanMatcherData": null, - "dependencyMatcherData": null, - "stringMatcherData": null + "partitions": [ + { + "treatment": "on", + "size": 0 + }, + { + "treatment": "off", + "size": 100 } - ] - }, - "partitions": [ - { - "treatment": "on", - "size": 100 - } - ], - "label": "whitelisted segment" - }, - { - "conditionType": "ROLLOUT", - "matcherGroup": { - "combiner": "AND", - "matchers": [ - { - "keySelector": { - "trafficType": "user", - "attribute": null - }, - "matcherType": "IN_SEGMENT", - "negate": false, - "userDefinedSegmentMatcherData": { - "segmentName": "Lucas_Segments_Tests" - }, - "whitelistMatcherData": null, - "unaryNumericMatcherData": null, - "betweenMatcherData": null, - "booleanMatcherData": null, - "dependencyMatcherData": null, - "stringMatcherData": null + ], + "label": "default rule" + } + ] + }, + { + "trafficTypeName": "user", + "name": "Lucas_Split", + "trafficAllocation": 32, + "trafficAllocationSeed": 2048379668, + "seed": 871802730, + "status": "ARCHIVED", + "killed": false, + "defaultTreatment": "v1", + "changeNumber": 1619720346272, + "algo": 2, + "configurations": {}, + "conditions": [ + { + "conditionType": "WHITELIST", + "matcherGroup": { + "combiner": "AND", + "matchers": [ + { + "keySelector": null, + "matcherType": "IN_SEGMENT", + "negate": false, + "userDefinedSegmentMatcherData": { + "segmentName": "Lucas_Segments_Tests" + }, + "whitelistMatcherData": null, + "unaryNumericMatcherData": null, + "betweenMatcherData": null, + "booleanMatcherData": null, + "dependencyMatcherData": null, + "stringMatcherData": null + } + ] + }, + "partitions": [ + { + "treatment": "on", + "size": 100 } - ] + ], + "label": "whitelisted segment" }, - "partitions": [ - { - "treatment": "on", - "size": 0 - }, - { - "treatment": "off", - "size": 0 + { + "conditionType": "ROLLOUT", + "matcherGroup": { + "combiner": "AND", + "matchers": [ + { + "keySelector": { + "trafficType": "user", + "attribute": null + }, + "matcherType": "IN_SEGMENT", + "negate": false, + "userDefinedSegmentMatcherData": { + "segmentName": "Lucas_Segments_Tests" + }, + "whitelistMatcherData": null, + "unaryNumericMatcherData": null, + "betweenMatcherData": null, + "booleanMatcherData": null, + "dependencyMatcherData": null, + "stringMatcherData": null + } + ] }, - { - "treatment": "v1", - "size": 100 - } - ], - "label": "in segment Lucas_Segments_Tests" - }, - { - "conditionType": "ROLLOUT", - "matcherGroup": { - "combiner": "AND", - "matchers": [ - { - "keySelector": { - "trafficType": "user", - "attribute": null - }, - "matcherType": "ALL_KEYS", - "negate": false, - "userDefinedSegmentMatcherData": null, - "whitelistMatcherData": null, - "unaryNumericMatcherData": null, - "betweenMatcherData": null, - "booleanMatcherData": null, - "dependencyMatcherData": null, - "stringMatcherData": null + "partitions": [ + { + "treatment": "on", + "size": 0 + }, + { + "treatment": "off", + "size": 0 + }, + { + "treatment": "v1", + "size": 100 } - ] + ], + "label": "in segment Lucas_Segments_Tests" }, - "partitions": [ - { - "treatment": "on", - "size": 0 - }, - { - "treatment": "off", - "size": 100 + { + "conditionType": "ROLLOUT", + "matcherGroup": { + "combiner": "AND", + "matchers": [ + { + "keySelector": { + "trafficType": "user", + "attribute": null + }, + "matcherType": "ALL_KEYS", + "negate": false, + "userDefinedSegmentMatcherData": null, + "whitelistMatcherData": null, + "unaryNumericMatcherData": null, + "betweenMatcherData": null, + "booleanMatcherData": null, + "dependencyMatcherData": null, + "stringMatcherData": null + } + ] }, - { - "treatment": "v1", - "size": 0 - } - ], - "label": "default rule" - } - ] - } - ], - "since": 1619720346271, - "till": 1619720346272 + "partitions": [ + { + "treatment": "on", + "size": 0 + }, + { + "treatment": "off", + "size": 100 + }, + { + "treatment": "v1", + "size": 0 + } + ], + "label": "default rule" + } + ] + } + ], + "s": 1619720346271, + "t": 1619720346272 + } }, { - "splits": [], - "since": 1619720346272, - "till": 1619720346272 + "ff": { + "d": [], + "s": 1619720346272, + "t": 1619720346272 + } } ], "segmentChanges": [ diff --git a/package-lock.json b/package-lock.json index 8ac4c29..056a286 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,15 @@ { "name": "@splitsoftware/splitio-sync-tools", - "version": "0.7.0", + "version": "1.0.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@splitsoftware/splitio-sync-tools", - "version": "0.7.0", + "version": "1.0.0", "license": "Apache-2.0", "dependencies": { - "@splitsoftware/splitio-commons": "2.3.0", + "@splitsoftware/splitio-commons": "2.4.0", "dotenv": "^9.0.1", "node-fetch": "^2.7.0", "yargs": "^17.0.1" @@ -1693,9 +1693,9 @@ } }, "node_modules/@splitsoftware/splitio-commons": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.3.0.tgz", - "integrity": "sha512-TRxutKjGw2JtlYhGYFW5T/2srF76hLDn9pNlwkHx6R0qDK7CqkjhFx/KU6LRqsibnmlh2aMl1I+TxblDncMDyA==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.4.0.tgz", + "integrity": "sha512-VjrzXe7zDM5oi+VWfNNAu1DtcsZl1he8c/MeC4O2SiNRid+Nurzs0ROziHEcBt/4nnCI7vZMNdM4FCcnZHMccA==", "license": "Apache-2.0", "dependencies": { "@types/ioredis": "^4.28.0", @@ -9208,9 +9208,9 @@ } }, "@splitsoftware/splitio-commons": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.3.0.tgz", - "integrity": "sha512-TRxutKjGw2JtlYhGYFW5T/2srF76hLDn9pNlwkHx6R0qDK7CqkjhFx/KU6LRqsibnmlh2aMl1I+TxblDncMDyA==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.4.0.tgz", + "integrity": "sha512-VjrzXe7zDM5oi+VWfNNAu1DtcsZl1he8c/MeC4O2SiNRid+Nurzs0ROziHEcBt/4nnCI7vZMNdM4FCcnZHMccA==", "requires": { "@types/ioredis": "^4.28.0", "tslib": "^2.3.1" diff --git a/package.json b/package.json index dee3822..740ef25 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@splitsoftware/splitio-sync-tools", - "version": "0.7.0", + "version": "1.0.0", "description": "Split JavaScript Sync Tools", "main": "lib/cjs/index.js", "module": "lib/esm/index.js", @@ -50,7 +50,7 @@ "prepublishOnly": "npm run check && npm run test && npm run build" }, "dependencies": { - "@splitsoftware/splitio-commons": "2.3.0", + "@splitsoftware/splitio-commons": "2.4.0", "dotenv": "^9.0.1", "node-fetch": "^2.7.0", "yargs": "^17.0.1" diff --git a/src/Synchronizer.ts b/src/Synchronizer.ts index b4eae52..268003c 100644 --- a/src/Synchronizer.ts +++ b/src/Synchronizer.ts @@ -2,8 +2,10 @@ import { splitApiFactory } from '@splitsoftware/splitio-commons/src/services/spl import { ISplitApi } from '@splitsoftware/splitio-commons/src/services/types'; import { IStorageAsync, ITelemetryCacheAsync } from '@splitsoftware/splitio-commons/src/storages/types'; import { ISettings } from '@splitsoftware/splitio-commons/src/types'; -import { SegmentsSynchronizer } from './synchronizers/SegmentsSynchronizer'; -import { SplitsSynchronizer } from './synchronizers/SplitsSynchronizer'; +import { segmentChangesFetcherFactory } from '@splitsoftware/splitio-commons/src/sync/polling/fetchers/segmentChangesFetcher'; +import { segmentChangesUpdaterFactory } from '@splitsoftware/splitio-commons/src/sync/polling/updaters/segmentChangesUpdater'; +import { splitChangesFetcherFactory } from '@splitsoftware/splitio-commons/src/sync/polling/fetchers/splitChangesFetcher'; +import { splitChangesUpdaterFactory } from '@splitsoftware/splitio-commons/src/sync/polling/updaters/splitChangesUpdater'; import { synchronizerStorageFactory } from './storages/synchronizerStorage'; import { eventsSubmitterFactory } from './submitters/eventsSubmitter'; import { impressionsSubmitterFactory } from './submitters/impressionsSubmitter'; @@ -36,13 +38,13 @@ export class Synchronizer { */ private _splitApi: ISplitApi; /** - * The local reference to the SegmentsUpdater instance from `@splitio/javascript-commons`. + * The local reference to the segmentChangesUpdater instance from `@splitio/javascript-commons`. */ - private _segmentsSynchronizer!: SegmentsSynchronizer; + private _segmentChangesUpdater!: ReturnType; /** - * The local reference to the SplitUpdater instance from `@splitio/javascript-commons`. + * The local reference to the splitChangesUpdater instance from `@splitio/javascript-commons`. */ - private _splitsSynchronizer!: SplitsSynchronizer; + private _splitChangesUpdater!: ReturnType; /** * The local reference to the EventsSynchronizer class. */ @@ -137,15 +139,16 @@ export class Synchronizer { new ImpressionCountsCacheInMemory() : undefined; - this._segmentsSynchronizer = new SegmentsSynchronizer( - this._splitApi.fetchSegmentChanges, - this.settings, + this._segmentChangesUpdater = segmentChangesUpdaterFactory( + this.settings.log, + segmentChangesFetcherFactory(this._splitApi.fetchSegmentChanges), this._storage.segments, ); - this._splitsSynchronizer = new SplitsSynchronizer( - this._splitApi.fetchSplitChanges, - this.settings, + this._splitChangesUpdater = splitChangesUpdaterFactory( + this.settings.log, + splitChangesFetcherFactory(this._splitApi.fetchSplitChanges, this.settings, this._storage), this._storage, + this.settings.sync.__splitFiltersValidation ); this._eventsSubmitter = eventsSubmitterFactory( this.settings.log, @@ -191,7 +194,7 @@ export class Synchronizer { private async preExecute(): Promise { const log = this.settings.log; if (!getFetch()) throw new Error('Global Fetch API is not available'); - log.info('Synchronizer: Execute'); + log.info(`Synchronizer: Execute. Version: ${this.settings.version}`); const areAPIsReady = await this._checkEndpointHealth(); if (!areAPIsReady) throw new Error('Health check of Split API endpoints failed'); @@ -260,11 +263,10 @@ export class Synchronizer { private async executeSplitsAndSegments(standalone = true) { if (standalone) await this.preExecute(); - // @TODO optimize SplitChangesUpdater to reduce storage operations ("inMemoryOperation" mode) - const isSplitsSyncSuccessful = await this._splitsSynchronizer.getSplitChanges(); + const isSplitsSyncSuccessful = await this._splitChangesUpdater(); this.settings.log.debug(`Feature flags Synchronizer task: ${isSplitsSyncSuccessful ? 'Successful' : 'Unsuccessful'}`); - const isSegmentsSyncSuccessful = await this._segmentsSynchronizer.getSegmentsChanges(); + const isSegmentsSyncSuccessful = await this._segmentChangesUpdater(); this.settings.log.debug(`Segments Synchronizer task: ${isSegmentsSyncSuccessful ? 'Successful' : 'Unsuccessful'}`); if (standalone) await this.postExecute(); diff --git a/src/settings/__tests__/index.spec.ts b/src/settings/__tests__/index.spec.ts index 12a1ac4..19d46c2 100644 --- a/src/settings/__tests__/index.spec.ts +++ b/src/settings/__tests__/index.spec.ts @@ -26,7 +26,7 @@ describe('synchronizerSettingsValidator', () => { expect(settings.scheduler.eventsPerPost).toBe(defaults.scheduler.eventsPerPost); expect(settings.scheduler.impressionsPerPost).toBe(defaults.scheduler.impressionsPerPost); expect(settings.scheduler.maxRetries).toBe(config.scheduler!.maxRetries); - expect(settings.sync.flagSpecVersion).toBe('1.1'); + expect(settings.sync.flagSpecVersion).toBe('1.3'); expect(settings.sync.requestOptions).toBe(config.sync!.requestOptions); }); diff --git a/src/settings/defaults.ts b/src/settings/defaults.ts index 5e5428c..6a89b50 100644 --- a/src/settings/defaults.ts +++ b/src/settings/defaults.ts @@ -4,8 +4,6 @@ */ const version = '@VERSION@'; -export const FLAG_SPEC_VERSION = '1.1'; - /** * Default values to create settings for the JavaScript Synchronizer. */ @@ -30,9 +28,6 @@ export const defaults = { // Number of retry attempts for posting impressions and events. maxRetries: 3, }, - sync: { - flagSpecVersion: FLAG_SPEC_VERSION, - }, version: `synctoolsjs-${version}`, streamingEnabled: false, }; diff --git a/src/settings/index.ts b/src/settings/index.ts index fbe533d..e590daa 100644 --- a/src/settings/index.ts +++ b/src/settings/index.ts @@ -1,12 +1,13 @@ import { ILogger } from '@splitsoftware/splitio-commons/src/logger/types'; import { ISettings } from '@splitsoftware/splitio-commons/src/types'; +import { FLAG_SPEC_VERSION } from '@splitsoftware/splitio-commons/src/utils/constants'; import { isIntegerNumber } from '@splitsoftware/splitio-commons/src/utils/lang'; import { settingsValidation } from '@splitsoftware/splitio-commons/src/utils/settingsValidation/index'; import { validateLogger } from '@splitsoftware/splitio-commons/src/utils/settingsValidation/logger/builtinLogger'; import { ISynchronizerSettings } from '../../types'; -import { defaults, FLAG_SPEC_VERSION } from './defaults'; +import { defaults } from './defaults'; -const FLAG_SPEC_VERSIONS = ['1.0', FLAG_SPEC_VERSION]; +const FLAG_SPEC_VERSIONS = ['1.0', '1.1', '1.2', FLAG_SPEC_VERSION]; /** * Object with some default values to instantiate the application and fullfil internal @@ -52,7 +53,7 @@ export function synchronizerSettingsValidator( const { scheduler, log } = settings; // @TODO validate synchronizerMode eventually - // @TODO: validate minimum and maximum value for config params. + // @TODO validate minimum and maximum value for config params. scheduler.eventsPerPost = validatePositiveInteger(log, 'eventsPerPost', scheduler.eventsPerPost, defaults.scheduler.eventsPerPost); scheduler.impressionsPerPost = validatePositiveInteger(log, 'impressionsPerPost', scheduler.impressionsPerPost, defaults.scheduler.impressionsPerPost); scheduler.maxRetries = validatePositiveInteger(log, 'maxRetries', scheduler.maxRetries, defaults.scheduler.maxRetries); diff --git a/src/synchronizers/SplitsSynchronizer.ts b/src/synchronizers/SplitsSynchronizer.ts index e12bbb6..798f1e5 100644 --- a/src/synchronizers/SplitsSynchronizer.ts +++ b/src/synchronizers/SplitsSynchronizer.ts @@ -54,7 +54,7 @@ export class SplitsSynchronizer { ) { this._storage = storage; this._settings = settings; - this._fetcher = splitChangesFetcherFactory(splitFetcher); + this._fetcher = splitChangesFetcherFactory(splitFetcher, settings, storage); this._splitUpdater = undefined; // @ts-ignore this._inMemoryStorage = InMemoryStorageFactory({ settings }); // @ts-ignore this._inMemoryStorageSnapshot = InMemoryStorageFactory({ settings }); @@ -142,7 +142,7 @@ export class SplitsSynchronizer { const registeredSegments = this._inMemoryStorage.segments.getRegisteredSegments(); - // @todo: Update segment definitions and change number + // @todo: Update rule-based segments, segment definitions and change number if (registeredSegments.length > 0) await this._storage.segments.registerSegments(registeredSegments); } catch (error) { diff --git a/types/index.d.ts b/types/index.d.ts index 2c86eab..cc349e5 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -149,11 +149,11 @@ declare module JsSyncTools { splitFilters?: SplitFilter[] /** * Feature Flag Spec version. Option to determine which version of the feature flag definitions are fetched and stored. - * Possible values are `'1.0'` and `'1.1'`. + * Possible values are `'1.0'`, `'1.1'`, `'1.2'`, and `'1.3'`. * - * @defaultValue `'1.1'` + * @defaultValue `'1.3'` */ - flagSpecVersion?: '1.0' | '1.1' + flagSpecVersion?: '1.0' | '1.1' | '1.2' | '1.3' /** * Impressions Collection Mode. Option to determine how impressions are going to be sent to Split Servers. *