Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: log diff #5072

Merged
merged 2 commits into from
Oct 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,8 @@
"devDependencies": {
"@apidevtools/swagger-parser": "10.1.0",
"@babel/core": "7.23.0",
"@swc/core": "1.3.92",
"@biomejs/biome": "1.2.2",
"@swc/core": "1.3.92",
"@swc/jest": "0.2.29",
"@types/bcryptjs": "2.4.4",
"@types/cors": "2.8.14",
Expand Down
66 changes: 66 additions & 0 deletions src/lib/features/feature-toggle/deep-diff.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
interface Difference {
index: (string | number)[];
reason: string;
valueA: any;
valueB: any;
}

export function deepDiff(arr1: any[], arr2: any[]): Difference[] | null {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there relationship between the arr1 and arr2 types?
deepDiff<T>(arr1: T[], arr2: T[]): Difference[] | null

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case they are different types.

const diff: Difference[] = [];

function compare(a: any, b: any, parentIndex: (string | number)[]): void {
if (Array.isArray(a) && Array.isArray(b)) {
if (a.length !== b.length) {
diff.push({
index: parentIndex,
reason: 'Different lengths',
valueA: a,
valueB: b,
});
} else {
for (let i = 0; i < a.length; i++) {
compare(a[i], b[i], parentIndex.concat(i));
}
}
} else if (
typeof a === 'object' &&
a !== null &&
typeof b === 'object' &&
b !== null
) {
const keysA = Object.keys(a);
const keysB = Object.keys(b);

if (!arraysEqual(keysA, keysB)) {
diff.push({
index: parentIndex,
reason: 'Different keys',
valueA: a,
valueB: b,
});
} else {
for (const key of keysA) {
compare(a[key], b[key], parentIndex.concat(key));
}
}
} else if (a !== b) {
diff.push({
index: parentIndex,
reason: 'Different values',
valueA: a,
valueB: b,
});
}
}

function arraysEqual(a: any[], b: any[]): boolean {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we move this function out?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd expect array equals signature to by typed: function arraysEqual<T>(a: T[], b: T[]): boolean

Copy link
Contributor

@kwasniew kwasniew Oct 17, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also it's not really array equality since we sort the elements.

return (
a.length === b.length &&
a.sort().every((val, index) => val === b.sort()[index])
);
}

compare(arr1, arr2, []);

return diff.length > 0 ? diff : null;
}
19 changes: 15 additions & 4 deletions src/lib/features/feature-toggle/feature-toggle-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ import { IDependentFeaturesReadModel } from '../dependent-features/dependent-fea
import EventService from '../../services/event-service';
import { DependentFeaturesService } from '../dependent-features/dependent-features-service';
import isEqual from 'lodash.isequal';
import { deepDiff } from './deep-diff';

interface IFeatureContext {
featureName: string;
Expand Down Expand Up @@ -1067,12 +1068,17 @@ class FeatureToggleService {
);

if (!equal) {
const difference = deepDiff(
featuresFromClientStore,
featuresFromFeatureToggleStore,
);
this.logger.warn(
'features from client-feature-toggle-store is not equal to features from feature-toggle-store',
'getPlaygroundFeatures: features from client-feature-toggle-store is not equal to features from feature-toggle-store',
difference,
);
}

const features = this.flagResolver.isEnabled('useLastSeenRefactor')
const features = this.flagResolver.isEnabled('separateAdminClientApi')
? featuresFromFeatureToggleStore
: featuresFromClientStore;

Expand Down Expand Up @@ -1113,12 +1119,17 @@ class FeatureToggleService {
);

if (!equal) {
const difference = deepDiff(
featuresFromClientStore,
featuresFromFeatureToggleStore,
);
this.logger.warn(
'features from client-feature-toggle-store is not equal to features from feature-toggle-store diff',
'getFeatureToggles: features from client-feature-toggle-store is not equal to features from feature-toggle-store diff',
difference,
);
}

const features = this.flagResolver.isEnabled('useLastSeenRefactor')
const features = this.flagResolver.isEnabled('separateAdminClientApi')
? featuresFromFeatureToggleStore
: featuresFromClientStore;

Expand Down
61 changes: 61 additions & 0 deletions src/lib/features/feature-toggle/tests/deep-diff.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { deepDiff } from '../deep-diff'; // Import the deepDiff function

describe('deepDiff', () => {
it('should return null for equal arrays', () => {
const arr1 = [1, 2, 3];
const arr2 = [1, 2, 3];
expect(deepDiff(arr1, arr2)).toBe(null);
});

it('should find differences in arrays with different lengths', () => {
const arr1 = [1, 2, 3];
const arr2 = [1, 2, 3, 4];
expect(deepDiff(arr1, arr2)).toEqual([
{
index: [],
reason: 'Different lengths',
valueA: arr1,
valueB: arr2,
},
]);
});

it('should find differences in arrays with different values', () => {
const arr1 = [1, 2, 3];
const arr2 = [1, 4, 3];
expect(deepDiff(arr1, arr2)).toEqual([
{
index: [1],
reason: 'Different values',
valueA: 2,
valueB: 4,
},
]);
});

it('should find differences in arrays with different keys in objects', () => {
const arr1 = [{ a: 1 }, { b: 2 }];
const arr2 = [{ a: 1 }, { c: 2 }];
expect(deepDiff(arr1, arr2)).toEqual([
{
index: [1],
reason: 'Different keys',
valueA: { b: 2 },
valueB: { c: 2 },
},
]);
});

it('should handle nested differences in objects', () => {
const arr1 = [{ a: { b: 1 } }, { c: { d: 2 } }];
const arr2 = [{ a: { b: 1 } }, { c: { d: 3 } }];
expect(deepDiff(arr1, arr2)).toEqual([
{
index: [1, 'c', 'd'],
reason: 'Different values',
valueA: 2,
valueB: 3,
},
]);
});
});