Skip to content

Conversation

@pgayvallet
Copy link
Contributor

@pgayvallet pgayvallet commented Nov 3, 2020

Summary

Fix #66387 Fix #36126 Fix #82403

Note: this is only displaying the technical error. Ideally, we would have a more user-friendly error, but this is harder to achieve, as there are some informations that we don't have on the client-side (such as the maxBodyPayload). Also, some errors are directly returned from HAPI (413) so it would not be possible to alter their format. I still think this is acceptable, and way better than not displaying any message at all.

Screenshot 2020-11-03 at 09 35 35

Screenshot 2020-11-03 at 09 35 26

Screenshot 2020-11-03 at 10 30 45

Screenshot 2020-11-03 at 12 01 08

Checklist

Release Note

Fix a bug causing Kibana to crash when importing a file with an invalid format from the saved object management section.

@pgayvallet pgayvallet added release_note:fix Team:Core Platform Core services: plugins, logging, config, saved objects, http, ES client, i18n, etc t// v7.10.1 v7.11.0 labels Nov 3, 2020
@pgayvallet pgayvallet changed the title SavedObjects management: display explicit import error in case of failure SavedObjects management: display explicit import error in case of failure and avoid invalid file to crash the server Nov 3, 2020
Comment on lines +31 to +39
export async function createSavedObjectsStreamFromNdJson(ndJsonStream: Readable) {
const savedObjects = await createPromiseFromStreams([
ndJsonStream,
createSplitStream('\n'),
createMapStream((str: string) => {
if (str && str.trim() !== '') {
return JSON.parse(str);
}
}),
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Soooo, long story short:

Uncatched errors from streams (either unhandled promises or plain errors) are causing the process to crash due to unhandled errors (forget streams were THAT much of a pain since I've been using observables)

The implementation of createPromiseFromStreams that is used here

const collectedObjects: Array<SavedObject<{ title?: string }>> = await createPromiseFromStreams([
readStream,

relies on stream.pipeline under the hood, that is supposed to intercept errors occurring during the stream/transform chain, however errors that occurred within a pipe of the argument observable are not.

The direct consequence is that any error thrown from the piping chain that is done in createSavedObjectsStreamFromNdJson was uncatched, therefor killing the server.

The correct solution would probably be to stop using streams and moving to observable instead, but these are significant changes (and collectSavedObjects is also used by the spaces plugin when copying to space), so the only solution I found for now was to collect the initial saved objects inside createSavedObjectsStreamFromNdJson and recreate a stream from that. That way, errors during the createSavedObjectsStreamFromNdJson stream chain are properly thrown via the added await createPromiseFromStreams. A FTR test has been added to assert that.

Note that this doesn't change the performances or memory usage: we were already collecting all emissions of the SO stream here before:

const collectedObjects: Array<SavedObject<{ title?: string }>> = await createPromiseFromStreams([

Copy link
Contributor

Choose a reason for hiding this comment

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

👍

I suspect if we're adding more saved object types to the export (to allow us to deprecate multi-tenancy) we might want to support real streaming imports/exports again and that will maybe allow us to remove the import payload size limit completely. But that's something to revisit once we know this is a requirement.

@pgayvallet pgayvallet marked this pull request as ready for review November 3, 2020 14:38
@pgayvallet pgayvallet requested a review from a team as a code owner November 3, 2020 14:38
@elasticmachine
Copy link
Contributor

Pinging @elastic/kibana-platform (Team:Platform)

Copy link
Contributor

@rudolf rudolf left a comment

Choose a reason for hiding this comment

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

We finally have import error messages in the UI 🙌

Comment on lines +31 to +39
export async function createSavedObjectsStreamFromNdJson(ndJsonStream: Readable) {
const savedObjects = await createPromiseFromStreams([
ndJsonStream,
createSplitStream('\n'),
createMapStream((str: string) => {
if (str && str.trim() !== '') {
return JSON.parse(str);
}
}),
Copy link
Contributor

Choose a reason for hiding this comment

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

👍

I suspect if we're adding more saved object types to the export (to allow us to deprecate multi-tenancy) we might want to support real streaming imports/exports again and that will maybe allow us to remove the import payload size limit completely. But that's something to revisit once we know this is a requirement.

@pgayvallet
Copy link
Contributor Author

I suspect if we're adding more saved object types to the export (to allow us to deprecate multi-tenancy) we might want to support real streaming imports/exports

For exports, probably.

For imports, I guess we would still need to collect all SO to perform a single bulkCreate operation, so we would still 'break' the stream at some point during the operation

}
>
<EuiFilePicker
accept=".ndjson, .json"
Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks 😄

@kibanamachine
Copy link
Contributor

💚 Build Succeeded

Metrics [docs]

async chunks size

id before after diff
savedObjectsManagement 187.3KB 187.6KB +304.0B

History

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

@pgayvallet pgayvallet merged commit e2cbde3 into elastic:master Nov 4, 2020
pgayvallet added a commit to pgayvallet/kibana that referenced this pull request Nov 4, 2020
…lure and avoid invalid file to crash the server (elastic#82406)

* display error cause in case of import failure

* avoid server crash when importing invalid file

* remove unused translations

* fix unit tests

* change savedObjects.maxImportPayloadBytes default to 25mb

* fix types and logic
pgayvallet added a commit to pgayvallet/kibana that referenced this pull request Nov 4, 2020
…lure and avoid invalid file to crash the server (elastic#82406)

* display error cause in case of import failure

* avoid server crash when importing invalid file

* remove unused translations

* fix unit tests

* change savedObjects.maxImportPayloadBytes default to 25mb

* fix types and logic
# Conflicts:
#	test/functional/apps/management/_import_objects.ts
pgayvallet added a commit that referenced this pull request Nov 4, 2020
…lure and avoid invalid file to crash the server (#82406) (#82613)

* display error cause in case of import failure

* avoid server crash when importing invalid file

* remove unused translations

* fix unit tests

* change savedObjects.maxImportPayloadBytes default to 25mb

* fix types and logic
# Conflicts:
#	test/functional/apps/management/_import_objects.ts
pgayvallet added a commit that referenced this pull request Nov 4, 2020
…lure and avoid invalid file to crash the server (#82406) (#82612)

* display error cause in case of import failure

* avoid server crash when importing invalid file

* remove unused translations

* fix unit tests

* change savedObjects.maxImportPayloadBytes default to 25mb

* fix types and logic
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release_note:fix Team:Core Platform Core services: plugins, logging, config, saved objects, http, ES client, i18n, etc t// v7.10.1 v7.11.0

Projects

None yet

5 participants