mirror of
https://github.com/Unleash/unleash.git
synced 2025-06-04 01:18:20 +02:00
fix: mutating delta events (#9303)
Fix a bug where delta events would be mutated due to Object.assign.
This commit is contained in:
parent
aa15fbee9a
commit
fa43420ab9
@ -183,4 +183,67 @@ describe('RevisionCache', () => {
|
|||||||
]),
|
]),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should not mutate previous feature-updated events when new events with the same feature name are added', () => {
|
||||||
|
const baseEvent: DeltaHydrationEvent = {
|
||||||
|
eventId: 1,
|
||||||
|
features: [
|
||||||
|
{
|
||||||
|
name: 'base-flag',
|
||||||
|
type: 'release',
|
||||||
|
enabled: true,
|
||||||
|
project: 'streaming-deltas',
|
||||||
|
stale: false,
|
||||||
|
strategies: [],
|
||||||
|
variants: [],
|
||||||
|
description: null,
|
||||||
|
impressionData: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
type: 'hydration',
|
||||||
|
segments: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
const deltaCache = new DeltaCache(baseEvent, 10);
|
||||||
|
|
||||||
|
const initialFeatureEvent: DeltaEvent = {
|
||||||
|
eventId: 129,
|
||||||
|
type: DELTA_EVENT_TYPES.FEATURE_UPDATED,
|
||||||
|
feature: {
|
||||||
|
impressionData: false,
|
||||||
|
enabled: false,
|
||||||
|
name: 'streaming-test',
|
||||||
|
description: null,
|
||||||
|
project: 'streaming-deltas',
|
||||||
|
stale: false,
|
||||||
|
type: 'release',
|
||||||
|
variants: [],
|
||||||
|
strategies: [],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
// This tests is to verify that the initialFeatureEvent is not mutated when a new event with the same feature name is added
|
||||||
|
// the following dirty way to clone this object is to avoid mutation on the comparison object. Because the object is passed by reference
|
||||||
|
// we would be comparing the same object with itself which would cause the expect check to always pass because the comparison would
|
||||||
|
// also change to match the object being compared.
|
||||||
|
deltaCache.addEvents([JSON.parse(JSON.stringify(initialFeatureEvent))]);
|
||||||
|
|
||||||
|
const updatedFeatureEvent: DeltaEvent = {
|
||||||
|
eventId: 130,
|
||||||
|
type: DELTA_EVENT_TYPES.FEATURE_UPDATED,
|
||||||
|
feature: {
|
||||||
|
impressionData: false,
|
||||||
|
enabled: true,
|
||||||
|
name: 'streaming-test',
|
||||||
|
description: null,
|
||||||
|
project: 'streaming-deltas',
|
||||||
|
stale: false,
|
||||||
|
type: 'release',
|
||||||
|
variants: [],
|
||||||
|
strategies: [{ name: 'new-strategy', parameters: {} }],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
deltaCache.addEvents([updatedFeatureEvent]);
|
||||||
|
// @ts-ignore
|
||||||
|
expect(deltaCache.events[1]).toStrictEqual(initialFeatureEvent);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -55,11 +55,13 @@ export class DeltaCache {
|
|||||||
for (const appliedEvent of events) {
|
for (const appliedEvent of events) {
|
||||||
switch (appliedEvent.type) {
|
switch (appliedEvent.type) {
|
||||||
case DELTA_EVENT_TYPES.FEATURE_UPDATED: {
|
case DELTA_EVENT_TYPES.FEATURE_UPDATED: {
|
||||||
const featureToUpdate = this.hydrationEvent.features.find(
|
const featureIndex = this.hydrationEvent.features.findIndex(
|
||||||
(feature) => feature.name === appliedEvent.feature.name,
|
(feature) => feature.name === appliedEvent.feature.name,
|
||||||
);
|
);
|
||||||
if (featureToUpdate) {
|
|
||||||
Object.assign(featureToUpdate, appliedEvent.feature);
|
if (featureIndex > -1) {
|
||||||
|
this.hydrationEvent.features[featureIndex] =
|
||||||
|
appliedEvent.feature;
|
||||||
} else {
|
} else {
|
||||||
this.hydrationEvent.features.push(appliedEvent.feature);
|
this.hydrationEvent.features.push(appliedEvent.feature);
|
||||||
}
|
}
|
||||||
@ -74,11 +76,12 @@ export class DeltaCache {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DELTA_EVENT_TYPES.SEGMENT_UPDATED: {
|
case DELTA_EVENT_TYPES.SEGMENT_UPDATED: {
|
||||||
const segmentToUpdate = this.hydrationEvent.segments.find(
|
const segmentIndex = this.hydrationEvent.segments.findIndex(
|
||||||
(segment) => segment.id === appliedEvent.segment.id,
|
(segment) => segment.id === appliedEvent.segment.id,
|
||||||
);
|
);
|
||||||
if (segmentToUpdate) {
|
if (segmentIndex > -1) {
|
||||||
Object.assign(segmentToUpdate, appliedEvent.segment);
|
this.hydrationEvent.segments[segmentIndex] =
|
||||||
|
appliedEvent.segment;
|
||||||
} else {
|
} else {
|
||||||
this.hydrationEvent.segments.push(appliedEvent.segment);
|
this.hydrationEvent.segments.push(appliedEvent.segment);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user