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

feat(bulk-import): adding sorting based on column in /imports #178

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

its-mitesh-kumar
Copy link
Contributor

@rhdh-gh-app
Copy link

rhdh-gh-app bot commented Dec 13, 2024

Changed Packages

Package Name Package Path Changeset Bump Current Version
@red-hat-developer-hub/backstage-plugin-bulk-import-backend workspaces/bulk-import/plugins/bulk-import-backend patch v5.2.1
@red-hat-developer-hub/backstage-plugin-bulk-import workspaces/bulk-import/plugins/bulk-import patch v1.10.7

@its-mitesh-kumar its-mitesh-kumar force-pushed the feat/bulk-import-import-job-sorting branch from 54ca224 to ba86c46 Compare December 13, 2024 13:45
Copy link
Member

@christoph-jerolimov christoph-jerolimov left a comment

Choose a reason for hiding this comment

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

Hi @its-mitesh-kumar, thanks for picking up also the backend work.

I added some comments, that IMHO we should remove the sorting in our backend, and add sorting params to the request calls for GitHub / Catalog API calls.

Let me know if I miss something and its not possible for some reason. And let the backend team and me know if you want continue with this.

Comment on lines 100 to 113
export enum AddedRepositoryColumnNameEnum {
repoName = 'repository.name',
organizationUrl = 'repository.organization',
repoUrl = 'repository.url',
catalogInfoYamlLastUpdated = 'lastUpdate',
catalogInfoYamlStatus = 'status',
}
export enum SortingOrderEnum {
ASC = 'asc',
DESC = 'desc',
}

Choose a reason for hiding this comment

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

Please respect the convention in this file

  • and add empty lines between each type definition
  • and it looks like enum keys here are all UPPER_CASE

Comment on lines 167 to +178
// sorting the output to make it deterministic and easy to navigate in the UI
sortImports(imports);

if (sortColumn) {
sortImports(imports, sortColumn, sortOrder);
}

Choose a reason for hiding this comment

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

Are we always fetching ALL elements in the backend?

And guess that we are and should not do that. So this sort function will only sort the current window (fetched page).

Instead of that we should pass the sorting to the backend calls like GitHub and the catalog API and remove the sorting from our backend.

Copy link
Member

Choose a reason for hiding this comment

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

Yes, it would be the best if we could sort and paginate at the Github side. Unfortunately, for /imports endpoint, I believe we are fetching all Catalog locations and then filtering those reachable with GH integrations. @rm3l might have valuable insights into the reasoning behind this solution and whether we can approach this more effectively. Maybe we can adjust filterLocationsAccessibleFromIntegrations here.

When fetching Catalog locations, pageNumber and pageSize are passed as params but not really used there, since we don't know which ones are actually reachable GH integrations. Maybe the best approach would be to switch stuff around and first fetch GH integrations, maybe it would help performance.

Copy link
Member

Choose a reason for hiding this comment

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

Indeed, IIRC, the /imports endpoint fetches Catalog locations first and only keeps those reachable from the configured GH integrations. Initially, it was querying GH first, but this was causing major performance issues, as reported in https://issues.redhat.com/browse/RHIDP-3680

Also, note that the imports may be coming from different sources (app-config, repos registered manually in Backstage, auto-discovery, ...), and the user may have configured several GH integrations (like different GH apps installed in multiple orgs).
That's essentially why the backend needed to aggregate such various sources to properly implement not only sorting, but also search and pagination, and return what the user is requesting.
But I guess pagination should help reduce the number of data fetched and iterated over.

That being said, open to better suggestions.

Comment on lines 53 to 78
function sortImports(
imports: Components.Schemas.Import[],
sortColumn: string = 'repository.name',
sortOrder: string = SortingOrderEnum.ASC,
) {
imports.sort((a, b) => {
if (a.repository?.name === undefined && b.repository?.name === undefined) {
return 0;
}
if (a.repository?.name === undefined) {
return -1;
}
if (b.repository?.name === undefined) {
return 1;
}
return a.repository.name.localeCompare(b.repository.name);
const value1 = getNestedValue(a, sortColumn);
const value2 = getNestedValue(b, sortColumn);
// Handle cases where values are undefined
if (value1 === undefined && value2 === undefined) return 0;
if (value1 === undefined) return SortingOrderEnum.ASC ? -1 : 1;
if (value2 === undefined) return SortingOrderEnum.ASC ? 1 : -1;
// Compare values based on sort order
return SortingOrderEnum.ASC === sortOrder
? value1.localeCompare(value2)
: value2.localeCompare(value1);
});
}

Choose a reason for hiding this comment

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

We should eliminate this and add the sorting parameter to the GitHub / Catalog API calls.

Copy link
Contributor Author

@its-mitesh-kumar its-mitesh-kumar Dec 23, 2024

Choose a reason for hiding this comment

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

Github APIs not supporting sorting on these params .

Comment on lines 16 to 30
export function getNestedValue<T>(obj: T, path: string): any {
return path
.split('.')
.reduce(
(acc, key) =>
acc && (acc as Record<string, any>)[key]
? (acc as Record<string, any>)[key]
: undefined,
obj,
);
}
export enum SortingOrderEnum {
ASC = 'asc',
DESC = 'desc',
}

Choose a reason for hiding this comment

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

We should eliminate this and add the sorting parameter to the GitHub / Catalog API calls.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Github APIs not supporting sorting on these params .

Comment on lines 364 to 376
sortColumnQueryParam:
in: query
name: sortColumn
description: The name of the column to sort by
required: false
schema:
type: string
Copy link
Member

Choose a reason for hiding this comment

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

It would be amazing if you could add for sortColumnQueryParam enum values with description of what each value means and then reuse the generated types.

Comment on lines 27 to 30
export enum SortingOrderEnum {
ASC = 'asc',
DESC = 'desc',
}
Copy link
Member

Choose a reason for hiding this comment

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

You have defined SortingOrderEnum also in types, ultimately it would be the best to reuse types generated in openapi.d.ts so we are not out of sync.

@its-mitesh-kumar its-mitesh-kumar force-pushed the feat/bulk-import-import-job-sorting branch from ba86c46 to ea7ffa3 Compare December 23, 2024 14:59
@its-mitesh-kumar
Copy link
Contributor Author

@christoph-jerolimov @dzemanov I have resolved the comments , Please re-review it

Copy link
Member

@dzemanov dzemanov left a comment

Choose a reason for hiding this comment

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

Tested with all sort values, on the backend and frontend. Works as expected except for when sortColumn is not specified. Please run prettier to fix failing tests :).

Comment on lines +101 to +108
export enum AddedRepositoryColumnNameEnum {
repoName = 'repository.name', // because of property name
repositoryName = 'repository.name',
organizationUrl = 'repository.organization',
repoUrl = 'repository.url',
catalogInfoYamlLastUpdated = 'lastUpdate',
catalogInfoYamlStatus = 'status',
}
Copy link
Member

Choose a reason for hiding this comment

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

Maybe it would be good to unify this and not repeat values. If repoName is needed, you can remove repositoryName and instead always use repoName.

Suggested change
export enum AddedRepositoryColumnNameEnum {
repoName = 'repository.name', // because of property name
repositoryName = 'repository.name',
organizationUrl = 'repository.organization',
repoUrl = 'repository.url',
catalogInfoYamlLastUpdated = 'lastUpdate',
catalogInfoYamlStatus = 'status',
}
export enum AddedRepositoryColumnNameEnum {
repoName = 'repository.name',
organizationUrl = 'repository.organization',
repoUrl = 'repository.url',
catalogInfoYamlLastUpdated = 'lastUpdate',
catalogInfoYamlStatus = 'status',
}

Comment on lines +102 to +103
const sortColumn = queryParams?.sortColumn;
const sortOrder = queryParams?.sortOrder;
Copy link
Member

Choose a reason for hiding this comment

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

You have defined in openapi.yaml both sortOrderQueryParam and sortColumnQueryParam to have default values if user does not provide them. But they are not used (they are not set automatically to default if undefined).
So either remove default values - in that case, we need to handle invalid option when user does not provide both of these parameters. Or I would suggest adding them here and then remove the change with if (sortColumn)

@dzemanov
Copy link
Member

dzemanov commented Jan 3, 2025

Also, please add changeset.

@@ -45,18 +49,31 @@ type FindAllImportsResponse =
| Components.Schemas.Import[]
| Components.Schemas.ImportJobListV2;

function sortImports(imports: Components.Schemas.Import[]) {
function sortImports(
Copy link
Member

Choose a reason for hiding this comment

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

@its-mitesh-kumar its-mitesh-kumar force-pushed the feat/bulk-import-import-job-sorting branch from e19fab3 to c2cff41 Compare January 6, 2025 08:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants