Skip to content

Commit 8bf9566

Browse files
Add getRegisteredSegment utility function, to compute the segments in use for server-side
1 parent a3f6481 commit 8bf9566

24 files changed

+97
-171
lines changed

src/storages/AbstractMySegmentsCacheSync.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export abstract class AbstractMySegmentsCacheSync implements ISegmentsCacheSync
1111
protected abstract addSegment(name: string): boolean
1212
protected abstract removeSegment(name: string): boolean
1313
protected abstract setChangeNumber(changeNumber?: number): boolean | void
14+
protected abstract getSegments(): string[]
1415

1516
/**
1617
* For server-side synchronizer: check if `key` is in `name` segment.
@@ -27,14 +28,14 @@ export abstract class AbstractMySegmentsCacheSync implements ISegmentsCacheSync
2728

2829

2930
// No-op. Not used in client-side.
30-
registerSegments(): boolean { return false; }
3131
update() { return false; }
3232

3333
/**
34-
* For server-side synchronizer: get the list of segments to fetch changes.
35-
* Also used for the `seC` (segment count) telemetry stat.
34+
* Used for the `seC` (segment count) telemetry stat.
3635
*/
37-
abstract getRegisteredSegments(): string[]
36+
getSegmentsCount() {
37+
return this.getSegments().length;
38+
}
3839

3940
/**
4041
* Only used for the `skC`(segment keys count) telemetry stat: 1 for client-side, and total count of keys in server-side.
@@ -68,7 +69,7 @@ export abstract class AbstractMySegmentsCacheSync implements ISegmentsCacheSync
6869
}
6970

7071
const names = ((segmentsData as IMySegmentsResponse).k || []).map(s => s.n).sort();
71-
const storedSegmentKeys = this.getRegisteredSegments().sort();
72+
const storedSegmentKeys = this.getSegments().sort();
7273

7374
// Extreme fast => everything is empty
7475
if (!names.length && !storedSegmentKeys.length) return false;

src/storages/AbstractSplitsCacheAsync.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export abstract class AbstractSplitsCacheAsync implements ISplitsCacheAsync {
3131
abstract trafficTypeExists(trafficType: string): Promise<boolean>
3232
abstract clear(): Promise<boolean | void>
3333

34-
// @TODO revisit segment-related methods ('usesSegments', 'getRegisteredSegments', 'registerSegments')
34+
// @TODO revisit segment-related methods ('usesSegments')
3535
// noop, just keeping the interface. This is used by standalone client-side API only, and so only implemented by InMemory and InLocalStorage.
3636
usesSegments(): Promise<boolean> {
3737
return Promise.resolve(true);

src/storages/KeyBuilderSS.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,6 @@ export class KeyBuilderSS extends KeyBuilder {
2929
this.versionablePrefix = `${metadata.s}/${metadata.n}/${metadata.i}`;
3030
}
3131

32-
buildRegisteredSegmentsKey() {
33-
return `${this.prefix}.segments.registered`;
34-
}
35-
3632
buildImpressionsKey() {
3733
return `${this.prefix}.impressions`;
3834
}

src/storages/__tests__/KeyBuilder.spec.ts

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,8 @@ test('KEYS / segments keys', () => {
3636
const expectedKey = `SPLITIO.segment.${segmentName}`;
3737
const expectedTill = `SPLITIO.segment.${segmentName}.till`;
3838

39-
const expectedSegmentRegistered = 'SPLITIO.segments.registered';
40-
4139
expect(builder.buildSegmentNameKey(segmentName) === expectedKey).toBe(true);
4240
expect(builder.buildSegmentTillKey(segmentName) === expectedTill).toBe(true);
43-
expect(builder.buildRegisteredSegmentsKey() === expectedSegmentRegistered).toBe(true);
44-
45-
// NOT USED
46-
// const expectedReady = 'SPLITIO.segments.ready';
47-
// expect(builder.buildSegmentsReady() === expectedReady).toBe(true);
4841
});
4942

5043
test('KEYS / traffic type keys', () => {

src/storages/inLocalStorage/MySegmentsCacheInLocal.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ export class MySegmentsCacheInLocal extends AbstractMySegmentsCacheSync {
4646
return localStorage.getItem(this.keys.buildSegmentNameKey(name)) === DEFINED;
4747
}
4848

49-
getRegisteredSegments(): string[] {
49+
protected getSegments(): string[] {
5050
// Scan current values from localStorage
5151
return Object.keys(localStorage).reduce((accum, key) => {
5252
let segmentName = this.keys.extractSegmentName(key);

src/storages/inLocalStorage/RBSegmentsCacheInLocal.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,10 @@ export class RBSegmentsCacheInLocal implements IRBSegmentsCacheSync {
105105
return item && JSON.parse(item);
106106
}
107107

108+
getAll(): IRBSegment[] {
109+
return this.getNames().map(name => this.get(name) as IRBSegment);
110+
}
111+
108112
contains(names: Set<string>): boolean {
109113
const namesArray = setToArray(names);
110114
const namesInStorage = this.getNames();

src/storages/inLocalStorage/__tests__/MySegmentsCacheInLocal.spec.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ test('SEGMENT CACHE / in LocalStorage', () => {
1717
expect(cache.getChangeNumber()).toBe(-1);
1818

1919
expect(cache.isInSegment('mocked-segment')).toBe(true);
20-
expect(cache.getRegisteredSegments()).toEqual(['mocked-segment', 'mocked-segment-2']);
2120
expect(cache.getKeysCount()).toBe(1);
2221
});
2322

@@ -29,7 +28,6 @@ test('SEGMENT CACHE / in LocalStorage', () => {
2928
});
3029

3130
expect(cache.isInSegment('mocked-segment')).toBe(false);
32-
expect(cache.getRegisteredSegments()).toEqual(['mocked-segment-2']);
3331
expect(cache.getKeysCount()).toBe(1);
3432
});
3533

src/storages/inMemory/MySegmentsCacheInMemory.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export class MySegmentsCacheInMemory extends AbstractMySegmentsCacheSync {
3838
return this.cn || -1;
3939
}
4040

41-
getRegisteredSegments() {
41+
protected getSegments() {
4242
return Object.keys(this.segmentCache);
4343
}
4444

src/storages/inMemory/RBSegmentsCacheInMemory.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ export class RBSegmentsCacheInMemory implements IRBSegmentsCacheSync {
5151
return this.cache[name] || null;
5252
}
5353

54+
getAll(): IRBSegment[] {
55+
return this.getNames().map(name => this.get(name) as IRBSegment);
56+
}
57+
5458
contains(names: Set<string>): boolean {
5559
const namesArray = setToArray(names);
5660
const namesInStorage = this.getNames();

src/storages/inMemory/SegmentsCacheInMemory.ts

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -36,24 +36,8 @@ export class SegmentsCacheInMemory implements ISegmentsCacheSync {
3636
this.segmentChangeNumber = {};
3737
}
3838

39-
private _registerSegment(name: string) {
40-
if (!this.segmentCache[name]) {
41-
this.segmentCache[name] = new Set<string>();
42-
}
43-
44-
return true;
45-
}
46-
47-
registerSegments(names: string[]) {
48-
for (let i = 0; i < names.length; i++) {
49-
this._registerSegment(names[i]);
50-
}
51-
52-
return true;
53-
}
54-
55-
getRegisteredSegments() {
56-
return Object.keys(this.segmentCache);
39+
getSegmentsCount() {
40+
return Object.keys(this.segmentCache).length;
5741
}
5842

5943
getKeysCount() {

src/storages/inMemory/TelemetryCacheInMemory.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,9 @@ export class TelemetryCacheInMemory implements ITelemetryCacheSync {
4949
iDe: this.getImpressionStats(DEDUPED),
5050
iDr: this.getImpressionStats(DROPPED),
5151
spC: this.splits && this.splits.getSplitNames().length,
52-
seC: this.segments && this.segments.getRegisteredSegments().length,
52+
seC: this.segments && this.segments.getSegmentsCount(),
5353
skC: this.segments && this.segments.getKeysCount(),
54-
lsC: this.largeSegments && this.largeSegments.getRegisteredSegments().length,
54+
lsC: this.largeSegments && this.largeSegments.getSegmentsCount(),
5555
lskC: this.largeSegments && this.largeSegments.getKeysCount(),
5656
sL: this.getSessionLength(),
5757
eQ: this.getEventStats(QUEUED),

src/storages/inMemory/__tests__/MySegmentsCacheInMemory.spec.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,13 @@ test('MY SEGMENTS CACHE / in memory', () => {
99
expect(cache.getChangeNumber()).toBe(-1);
1010

1111
expect(cache.isInSegment('mocked-segment')).toBe(true);
12-
expect(cache.getRegisteredSegments()).toEqual(['mocked-segment', 'mocked-segment-2']);
1312
expect(cache.getKeysCount()).toBe(1);
1413

1514
expect(cache.resetSegments({ k: [{ n: 'mocked-segment-2' }], cn: 150})).toBe(true);
1615

1716
expect(cache.isInSegment('mocked-segment')).toBe(false);
18-
expect(cache.getRegisteredSegments()).toEqual(['mocked-segment-2']);
1917
expect(cache.getKeysCount()).toBe(1);
2018

2119
cache.clear();
22-
expect(cache.getRegisteredSegments()).toEqual([]);
2320
expect(cache.getChangeNumber()).toBe(-1);
2421
});

src/storages/inMemory/__tests__/SegmentsCacheInMemory.spec.ts

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,4 @@ describe('SEGMENTS CACHE IN MEMORY', () => {
2929
expect(cache.getKeysCount()).toBe(0);
3030
});
3131

32-
test('registerSegment / getRegisteredSegments', async () => {
33-
const cache = new SegmentsCacheInMemory();
34-
35-
await cache.registerSegments(['s1']);
36-
await cache.registerSegments(['s2']);
37-
await cache.registerSegments(['s2', 's3', 's4']);
38-
39-
const segments = cache.getRegisteredSegments();
40-
41-
['s1', 's2', 's3', 's4'].forEach(s => expect(segments.indexOf(s) !== -1).toBe(true));
42-
});
43-
4432
});

src/storages/inRedis/RBSegmentsCacheInRedis.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@ export class RBSegmentsCacheInRedis implements IRBSegmentsCacheAsync {
3030
);
3131
}
3232

33+
getAll(): Promise<IRBSegment[]> {
34+
return this.getNames().then(names => {
35+
return Promise.all(names.map(name => this.get(name) as Promise<IRBSegment>));
36+
});
37+
}
38+
3339
contains(names: Set<string>): Promise<boolean> {
3440
const namesArray = setToArray(names);
3541
return this.getNames().then(namesInStorage => {

src/storages/inRedis/SegmentsCacheInRedis.ts

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -51,18 +51,6 @@ export class SegmentsCacheInRedis implements ISegmentsCacheAsync {
5151
});
5252
}
5353

54-
registerSegments(segments: string[]) {
55-
if (segments.length) {
56-
return this.redis.sadd(this.keys.buildRegisteredSegmentsKey(), segments).then(() => true);
57-
} else {
58-
return Promise.resolve(true);
59-
}
60-
}
61-
62-
getRegisteredSegments() {
63-
return this.redis.smembers(this.keys.buildRegisteredSegmentsKey());
64-
}
65-
6654
// @TODO remove or implement. It is not being used.
6755
clear() {
6856
return Promise.resolve();

src/storages/inRedis/__tests__/SegmentsCacheInRedis.spec.ts

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -36,21 +36,4 @@ describe('SEGMENTS CACHE IN REDIS', () => {
3636
await connection.disconnect();
3737
});
3838

39-
test('registerSegment / getRegisteredSegments', async () => {
40-
const connection = new RedisAdapter(loggerMock);
41-
const cache = new SegmentsCacheInRedis(loggerMock, keys, connection);
42-
43-
await cache.registerSegments(['s1']);
44-
await cache.registerSegments(['s2']);
45-
await cache.registerSegments(['s2', 's3', 's4']);
46-
47-
const segments = await cache.getRegisteredSegments();
48-
49-
['s1', 's2', 's3', 's4'].forEach(s => expect(segments.indexOf(s) !== -1).toBe(true));
50-
51-
// Teardown
52-
await connection.del(await connection.keys(`${prefix}.segment*`)); // @TODO use `cache.clear` method when implemented
53-
await connection.disconnect();
54-
});
55-
5639
});

src/storages/pluggable/RBSegmentsCachePluggable.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@ export class RBSegmentsCachePluggable implements IRBSegmentsCacheAsync {
2929
);
3030
}
3131

32+
getAll(): Promise<IRBSegment[]> {
33+
return this.getNames().then(names => {
34+
return Promise.all(names.map(name => this.get(name) as Promise<IRBSegment>));
35+
});
36+
}
37+
3238
contains(names: Set<string>): Promise<boolean> {
3339
const namesArray = setToArray(names);
3440
return this.getNames().then(namesInStorage => {

src/storages/pluggable/SegmentsCachePluggable.ts

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -62,26 +62,6 @@ export class SegmentsCachePluggable implements ISegmentsCacheAsync {
6262
});
6363
}
6464

65-
/**
66-
* Add the given segment names to the set of registered segments.
67-
* The returned promise is resolved when the operation success,
68-
* or rejected if it fails (e.g., wrapper operation fails).
69-
*/
70-
registerSegments(segments: string[]) {
71-
if (segments.length) {
72-
return this.wrapper.addItems(this.keys.buildRegisteredSegmentsKey(), segments);
73-
} else {
74-
return Promise.resolve();
75-
}
76-
}
77-
78-
/**
79-
* Returns a promise that resolves with the set of registered segments in a list,
80-
* or rejected if it fails (e.g., wrapper operation fails).
81-
*/
82-
getRegisteredSegments() {
83-
return this.wrapper.getItems(this.keys.buildRegisteredSegmentsKey());
84-
}
8565

8666
// @TODO implement if required by DataLoader or Producer mode
8767
clear(): Promise<boolean> {

src/storages/pluggable/__tests__/SegmentsCachePluggable.spec.ts

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -37,16 +37,4 @@ describe('SEGMENTS CACHE PLUGGABLE', () => {
3737
expect(await cache.isInSegment('inexistent-segment', 'a')).toBe(false);
3838
});
3939

40-
test('registerSegment / getRegisteredSegments', async () => {
41-
const cache = new SegmentsCachePluggable(loggerMock, keyBuilder, wrapperMock);
42-
43-
await cache.registerSegments(['s1']);
44-
await cache.registerSegments(['s2']);
45-
await cache.registerSegments(['s2', 's3', 's4']);
46-
47-
const segments = await cache.getRegisteredSegments();
48-
49-
['s1', 's2', 's3', 's4'].forEach(s => expect(segments.indexOf(s) !== -1).toBe(true));
50-
});
51-
5240
});

src/storages/types.ts

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@ export interface IRBSegmentsCacheBase {
229229
getChangeNumber(): MaybeThenable<number>,
230230
clear(): MaybeThenable<boolean | void>,
231231
contains(names: Set<string>): MaybeThenable<boolean>,
232+
getAll(): MaybeThenable<IRBSegment[]>,
232233
}
233234

234235
export interface IRBSegmentsCacheSync extends IRBSegmentsCacheBase {
@@ -237,6 +238,7 @@ export interface IRBSegmentsCacheSync extends IRBSegmentsCacheBase {
237238
getChangeNumber(): number,
238239
clear(): void,
239240
contains(names: Set<string>): boolean,
241+
getAll(): IRBSegment[],
240242
// Used only for smart pausing in client-side standalone. Returns true if the storage contains a RBSegment using segments or large segments matchers
241243
usesSegments(): boolean,
242244
}
@@ -247,14 +249,13 @@ export interface IRBSegmentsCacheAsync extends IRBSegmentsCacheBase {
247249
getChangeNumber(): Promise<number>,
248250
clear(): Promise<boolean | void>,
249251
contains(names: Set<string>): Promise<boolean>,
252+
getAll(): Promise<IRBSegment[]>,
250253
}
251254

252255
/** Segments cache */
253256

254257
export interface ISegmentsCacheBase {
255258
isInSegment(name: string, key?: string): MaybeThenable<boolean> // different signature on Server and Client-Side
256-
registerSegments(names: string[]): MaybeThenable<boolean | void> // only for Server-Side
257-
getRegisteredSegments(): MaybeThenable<string[]> // only for Server-Side
258259
getChangeNumber(name: string): MaybeThenable<number | undefined> // only for Server-Side
259260
update(name: string, addedKeys: string[], removedKeys: string[], changeNumber: number): MaybeThenable<boolean> // only for Server-Side
260261
clear(): MaybeThenable<boolean | void>
@@ -263,19 +264,17 @@ export interface ISegmentsCacheBase {
263264
// Same API for both variants: SegmentsCache and MySegmentsCache (client-side API)
264265
export interface ISegmentsCacheSync extends ISegmentsCacheBase {
265266
isInSegment(name: string, key?: string): boolean
266-
registerSegments(names: string[]): boolean
267-
getRegisteredSegments(): string[]
268-
getKeysCount(): number // only used for telemetry
269267
getChangeNumber(name?: string): number | undefined
270268
update(name: string, addedKeys: string[], removedKeys: string[], changeNumber: number): boolean // only for Server-Side
271269
resetSegments(segmentsData: MySegmentsData | IMySegmentsResponse): boolean // only for Sync Client-Side
272270
clear(): void
271+
// only used for telemetry:
272+
getKeysCount(): number
273+
getSegmentsCount(): number
273274
}
274275

275276
export interface ISegmentsCacheAsync extends ISegmentsCacheBase {
276277
isInSegment(name: string, key: string): Promise<boolean>
277-
registerSegments(names: string[]): Promise<boolean | void>
278-
getRegisteredSegments(): Promise<string[]>
279278
getChangeNumber(name: string): Promise<number | undefined>
280279
update(name: string, addedKeys: string[], removedKeys: string[], changeNumber: number): Promise<boolean>
281280
clear(): Promise<boolean | void>

src/sync/polling/syncTasks/segmentsSyncTask.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export function segmentsSyncTaskFactory(
2121
segmentChangesUpdaterFactory(
2222
settings.log,
2323
segmentChangesFetcherFactory(fetchSegmentChanges),
24-
storage.segments,
24+
storage,
2525
readiness,
2626
),
2727
settings.scheduler.segmentsRefreshRate,

0 commit comments

Comments
 (0)