Skip to content

Commit

Permalink
fix: add some index to speed up the resolution of expands (#825)
Browse files Browse the repository at this point in the history
* fix: add some index to speed up the resolution of expands

* chore: fix tests

* chore: missing code

* chore: centralize coding

* chore: centralize coding more
  • Loading branch information
nlunets committed Jun 10, 2024
1 parent 0320312 commit 0f34945
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 12 deletions.
5 changes: 5 additions & 0 deletions .changeset/twenty-numbers-yawn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sap-ux/fe-mockserver-core': patch
---

Add index to speed up the mockserver
1 change: 1 addition & 0 deletions packages/fe-mockserver-core/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export interface ConfigService {
debug: boolean;
noETag: boolean;
contextBasedIsolation: boolean;
forceNullableValuesToNull: boolean;
strictKeyMode: boolean;
watch: boolean;
}
Expand Down
21 changes: 13 additions & 8 deletions packages/fe-mockserver-core/src/data/entitySets/entitySet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ function prepareLiteral(literal: string, propertyType: string) {
*
*/
export class MockDataEntitySet implements EntitySetInterface {
private _resolvedProperties: Record<string, Property> = {};
public static async read(
mockDataRootFolder: string,
entity: string,
Expand Down Expand Up @@ -302,16 +303,20 @@ export class MockDataEntitySet implements EntitySetInterface {
}

public getProperty(identifier: string) {
let resolvedPath;
if (this.entitySetDefinition) {
resolvedPath = this.dataAccess
.getMetadata()
.resolvePath('/' + this.entitySetDefinition.name + '/' + identifier);
} else {
resolvedPath = this.entityTypeDefinition.resolvePath(identifier, true);
if (!this._resolvedProperties[identifier]) {
let resolvedPath;
if (this.entitySetDefinition) {
resolvedPath = this.dataAccess
.getMetadata()
.resolvePath('/' + this.entitySetDefinition.name + '/' + identifier);
} else {
resolvedPath = this.entityTypeDefinition.resolvePath(identifier, true);
}

this._resolvedProperties[identifier] = resolvedPath.target;
}

return resolvedPath.target;
return this._resolvedProperties[identifier];
}

public checkFilter(
Expand Down
57 changes: 54 additions & 3 deletions packages/fe-mockserver-core/src/mockdata/fileBasedMockData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ function compareRowData(
}
export class FileBasedMockData {
protected _mockData: object[];
protected _keyIndex: Record<string, number>;
protected _hierarchyTree: Record<string, Record<string, any>> = {};
protected _entityType: EntityType;
protected _mockDataEntitySet: EntitySetInterface;
Expand Down Expand Up @@ -164,6 +165,11 @@ export class FileBasedMockData {
} else if (mockEntry.hasOwnProperty(prop.name) && isComplexTypeDefinition(prop.targetType)) {
// If the property is defined from a complex type we should validate the property of the complex type
this.validateProperties(mockEntry[prop.name], prop.targetType.properties);
} else if (
mockEntry.hasOwnProperty(prop.name) &&
['Edm.Int16', 'Edm.Int32', 'Edm.Int64'].includes(prop.type)
) {
mockEntry[prop.name] = parseInt(mockEntry[prop.name], 10);
}
});
}
Expand Down Expand Up @@ -213,6 +219,7 @@ export class FileBasedMockData {

async addEntry(mockEntry: any, _odataRequest: ODataRequest): Promise<void> {
this._mockData.push(mockEntry);
this.createKeyIndex();
}

async updateEntry(
Expand All @@ -225,8 +232,34 @@ export class FileBasedMockData {
this._mockData[dataIndex] = updatedData;
}

fetchIndexFromKey(keys: Property[], keyValues: KeyDefinitions, _odataRequest: ODataRequest): number | undefined {
const fetchedKeys = Object.keys(keyValues);
const areAllKeysMatched = keys.every((key) => {
return fetchedKeys.includes(key.name);
});
if (areAllKeysMatched) {
if (!this._keyIndex) {
this.createKeyIndex();
}
const key = keys
.map((keyProp) => {
const keyValue = keyValues[keyProp.name];
if (keyValue && typeof keyValue === 'string' && keyValue.startsWith("guid'")) {
return keyValue.substring(5, keyValue.length - 1);
}
return keyValues[keyProp.name];
})
.join('-');
return this._keyIndex[key];
}
}

fetchEntries(keyValues: KeyDefinitions, _odataRequest: ODataRequest): object[] {
const keys = this._entityType.keys;
const indexFromKey = this.fetchIndexFromKey(keys, keyValues, _odataRequest);
if (indexFromKey && indexFromKey !== -1) {
return [this._mockData[indexFromKey]];
}
return this._mockData.filter((mockData) => {
return Object.keys(keyValues).every(this.checkKeyValues(mockData, keyValues, keys, _odataRequest));
});
Expand All @@ -247,12 +280,29 @@ export class FileBasedMockData {
return cloneDeep(this._mockData);
}

protected getDataIndex(keyValues: KeyDefinitions, _odataRequest: ODataRequest): number {
protected createKeyIndex() {
const keys = this._entityType.keys;
return this._mockData.findIndex((mockData) => {
return Object.keys(keyValues).every(this.checkKeyValues(mockData, keyValues, keys, _odataRequest));
this._keyIndex = {};
this._mockData.forEach((mockData: any, index: number) => {
const key = keys
.map((keyProp) => {
return mockData[keyProp.name];
})
.join('-');
this._keyIndex[key] = index;
});
}
protected getDataIndex(keyValues: KeyDefinitions, _odataRequest: ODataRequest): number {
const keys = this._entityType.keys;
const entryFromKeys = this.fetchIndexFromKey(keys, keyValues, _odataRequest);
if (entryFromKeys) {
return entryFromKeys;
} else {
return this._mockData.findIndex((mockData) => {
return Object.keys(keyValues).every(this.checkKeyValues(mockData, keyValues, keys, _odataRequest));
});
}
}

private checkKeyValues(mockData: object, keyValues: KeyDefinitions, keys: Property[], _odataRequest: ODataRequest) {
return (keyName: string) => {
Expand All @@ -271,6 +321,7 @@ export class FileBasedMockData {
if (dataIndex !== -1) {
this._mockData.splice(dataIndex, 1);
}
this.createKeyIndex();
}

protected getDefaultValueFromType(
Expand Down
3 changes: 2 additions & 1 deletion packages/ui5-middleware-fe-mockserver/src/configResolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@ function processServicesConfig(
debug: inService.debug,
strictKeyMode: inService.strictKeyMode,
generateMockData: inService.generateMockData,
contextBasedIsolation: inService.contextBasedIsolation
contextBasedIsolation: inService.contextBasedIsolation,
forceNullableValuesToNull: inService.forceNullableValuesToNull
} as any;
const metadataPath = inService.metadataPath || inService.metadataXmlPath || inService.metadataCdsPath;
if (metadataPath) {
Expand Down

0 comments on commit 0f34945

Please sign in to comment.