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

[Files] Adds bulk get method #155636

Merged
merged 12 commits into from
Apr 27, 2023
Merged

[Files] Adds bulk get method #155636

merged 12 commits into from
Apr 27, 2023

Conversation

vadimkibana
Copy link
Contributor

@vadimkibana vadimkibana commented Apr 24, 2023

Summary

Closes #155369

Checklist

Delete any items that are not applicable to this PR.

For maintainers

@vadimkibana vadimkibana changed the title [Files] adds bulk get method [Files] Adds bulk get method Apr 24, 2023
@vadimkibana vadimkibana added review release_note:skip Skip the PR/issue when compiling release notes Team:SharedUX Team label for AppEx-SharedUX (formerly Global Experience) feature:Files v8.8.0 labels Apr 24, 2023
@vadimkibana vadimkibana marked this pull request as ready for review April 24, 2023 14:53
@vadimkibana vadimkibana requested a review from a team as a code owner April 24, 2023 14:53
@elasticmachine
Copy link
Contributor

Pinging @elastic/appex-sharedux (Team:SharedUX)

@vadimkibana
Copy link
Contributor Author

@elasticmachine merge upstream

@vadimkibana vadimkibana enabled auto-merge (squash) April 25, 2023 14:15
@@ -120,6 +121,10 @@ export class EsIndexFilesMetadataClient<M = unknown> implements FileMetadataClie
};
}

async bulkGet({ ids }: BulkGetArg): Promise<FileDescriptor[]> {
return await Promise.all(ids.map((id) => this.get({ id })));
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't believe cases will be using this adapter but could this use elasticsearch's mget API?

If that's not an option, we've used p-map in cases to limit the number of concurrent requests: https://github.com/sindresorhus/p-map

Copy link
Contributor

Choose a reason for hiding this comment

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

Good point. I've added p-limit in 0a65355

const metadatas = await this.metadataClient.bulkGet({ ids });
const result = metadatas.map(({ id, metadata }) => {
if (metadata.Status === 'DELETED') {
throw new FileNotFoundError('File has been deleted');
Copy link
Contributor

@jonathan-buttner jonathan-buttner Apr 25, 2023

Choose a reason for hiding this comment

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

I don't think this will provide the functionality we need in cases. Cases is intentionally doing a promise settled to allow for some files to not exist but still not have the entire api call throw an error.

https://github.com/elastic/kibana/blob/main/x-pack/plugins/cases/server/client/attachments/bulk_delete.ts#L137

This way we can continue with our deletion logic even when some files don't exist. Could we still return normally here but provide a way to see which ids failed and which succeeded?

Copy link
Contributor

@sebelga sebelga Apr 26, 2023

Choose a reason for hiding this comment

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

Good points 👍
In c1030a0 I've added 2 options:

  • throwIfNotFound - If set to false then null is returned
  • format ("array" | "map") - If set to map then a map of id/File (or null if throwIfNotFound is false) is returned
it('returns the files under a map of id/File', async () => {
  const file1 = await createDisposableFile({ fileKind, name: 'test' });
  const unknownID = 'foo';

  const myFiles = await fileService.bulkGetById({
    ids: [file1.id, unknownID],
    throwIfNotFound: false, // do not throw
    format: 'map', // returns a map
  });

  expect(myFiles[file1?.id]?.id).toBe(file1?.id); // true
  expect(myFiles[unknownID]).toBe(null); // true
});

would that work?

});
return result;
} catch (e) {
if (SavedObjectsErrorHelpers.isNotFoundError(e)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Will the saved object client throw an error if one of the files does not exist? I think it will just mark that item in the array with the error field.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes you are right, that's how it is returned from the saved object bulkGet

if (docNotFound) {
  return {
    id,
    type,
    error: errorContent(SavedObjectsErrorHelpers.createGenericNotFoundError(type, id)),
  } as any as SavedObject<T>;
}

In b97a0f1 I removed this condition and made sure we return null in case of an error when fetching one of the saved object.

Copy link
Contributor

@sebelga sebelga left a comment

Choose a reason for hiding this comment

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

Great job @vadimkibana ! I made some changes based on @jonathan-buttner feedback. Jonathan can you have another look and let me know if the new options would help for cases? Cheers 👍

@@ -120,6 +121,10 @@ export class EsIndexFilesMetadataClient<M = unknown> implements FileMetadataClie
};
}

async bulkGet({ ids }: BulkGetArg): Promise<FileDescriptor[]> {
return await Promise.all(ids.map((id) => this.get({ id })));
Copy link
Contributor

Choose a reason for hiding this comment

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

Good point. I've added p-limit in 0a65355

const metadatas = await this.metadataClient.bulkGet({ ids });
const result = metadatas.map(({ id, metadata }) => {
if (metadata.Status === 'DELETED') {
throw new FileNotFoundError('File has been deleted');
Copy link
Contributor

@sebelga sebelga Apr 26, 2023

Choose a reason for hiding this comment

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

Good points 👍
In c1030a0 I've added 2 options:

  • throwIfNotFound - If set to false then null is returned
  • format ("array" | "map") - If set to map then a map of id/File (or null if throwIfNotFound is false) is returned
it('returns the files under a map of id/File', async () => {
  const file1 = await createDisposableFile({ fileKind, name: 'test' });
  const unknownID = 'foo';

  const myFiles = await fileService.bulkGetById({
    ids: [file1.id, unknownID],
    throwIfNotFound: false, // do not throw
    format: 'map', // returns a map
  });

  expect(myFiles[file1?.id]?.id).toBe(file1?.id); // true
  expect(myFiles[unknownID]).toBe(null); // true
});

would that work?

});
return result;
} catch (e) {
if (SavedObjectsErrorHelpers.isNotFoundError(e)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Yes you are right, that's how it is returned from the saved object bulkGet

if (docNotFound) {
  return {
    id,
    type,
    error: errorContent(SavedObjectsErrorHelpers.createGenericNotFoundError(type, id)),
  } as any as SavedObject<T>;
}

In b97a0f1 I removed this condition and made sure we return null in case of an error when fetching one of the saved object.

Copy link
Contributor

@jonathan-buttner jonathan-buttner left a comment

Choose a reason for hiding this comment

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

Thanks for the changes!

@kibana-ci
Copy link
Collaborator

💚 Build Succeeded

Metrics [docs]

Public APIs missing comments

Total count of every public API that lacks a comment. Target amount is 0. Run node scripts/build_api_docs --plugin [yourplugin] --stats comments for more detailed information.

id before after diff
files 10 23 +13

Public APIs missing exports

Total count of every type that is part of your API that should be exported but is not. This will cause broken links in the API documentation system. Target amount is 0. Run node scripts/build_api_docs --plugin [yourplugin] --stats exports for more detailed information.

id before after diff
files 6 8 +2
Unknown metric groups

API count

id before after diff
files 219 235 +16

ESLint disabled line counts

id before after diff
enterpriseSearch 17 19 +2
securitySolution 399 402 +3
total +5

Total ESLint disabled count

id before after diff
enterpriseSearch 18 20 +2
securitySolution 479 482 +3
total +5

History

To update your PR or re-run it, just comment with:
@elasticmachine merge upstream

@sebelga sebelga self-assigned this Apr 27, 2023
Copy link
Contributor

@sebelga sebelga left a comment

Choose a reason for hiding this comment

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

Approving!

@vadimkibana vadimkibana merged commit a0cd724 into elastic:main Apr 27, 2023
kibanamachine pushed a commit to kibanamachine/kibana that referenced this pull request Apr 27, 2023
## Summary

Closes elastic#155369

### Checklist

Delete any items that are not applicable to this PR.

- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios

### For maintainers

- [x] This was checked for breaking API changes and was [labeled
appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)

---------

Co-authored-by: kibanamachine <[email protected]>
(cherry picked from commit a0cd724)
@kibanamachine
Copy link
Contributor

💚 All backports created successfully

Status Branch Result
8.8

Note: Successful backport PRs will be merged automatically after passing CI.

Questions ?

Please refer to the Backport tool documentation

@kibanamachine kibanamachine added the backport missing Added to PRs automatically when the are determined to be missing a backport. label Jan 16, 2024
@kibanamachine
Copy link
Contributor

Looks like this PR has a backport PR but it still hasn't been merged. Please merge it ASAP to keep the branches relatively in sync.

4 similar comments
@kibanamachine
Copy link
Contributor

Looks like this PR has a backport PR but it still hasn't been merged. Please merge it ASAP to keep the branches relatively in sync.

@kibanamachine
Copy link
Contributor

Looks like this PR has a backport PR but it still hasn't been merged. Please merge it ASAP to keep the branches relatively in sync.

@kibanamachine
Copy link
Contributor

Looks like this PR has a backport PR but it still hasn't been merged. Please merge it ASAP to keep the branches relatively in sync.

@kibanamachine
Copy link
Contributor

Looks like this PR has a backport PR but it still hasn't been merged. Please merge it ASAP to keep the branches relatively in sync.

@jbudz jbudz added the backport:skip This commit does not require backporting label Sep 30, 2024
@kibanamachine kibanamachine removed the backport missing Added to PRs automatically when the are determined to be missing a backport. label Sep 30, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backport:skip This commit does not require backporting feature:Files release_note:skip Skip the PR/issue when compiling release notes review Team:SharedUX Team label for AppEx-SharedUX (formerly Global Experience) v8.8.0 v8.9.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Files] Expose bulk get files API from the files service on the backend
7 participants