Skip to content

Conversation

@ppisljar
Copy link
Contributor

@ppisljar ppisljar commented Jul 12, 2021

Summary

adds initial guide doc for persistable state

resolves #103105

@elasticmachine
Copy link
Contributor

Pinging @elastic/kibana-app-services (Team:AppServices)

@ppisljar ppisljar added the release_note:skip Skip the PR/issue when compiling release notes label Jul 12, 2021
@ppisljar ppisljar requested a review from stacey-gammon July 12, 2021 11:17
Copy link

@stacey-gammon stacey-gammon left a comment

Choose a reason for hiding this comment

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

Only reviewed a little bit because I have some code change suggestions I'd like to discuss before we merge this.

ppisljar and others added 2 commits July 13, 2021 14:43
Co-authored-by: Stacey Gammon <gammon@elastic.co>
and reference extraction and injection methods correctly use the correct `PersistableStateService` implementation.

If a saved object contains state from another plugin, the <DocLink id="kibCoreSavedObjectsPluginApi" section="iaf33fb81-e64a-11eb-8631-9d6e17a74ca4" text-"SavedObjectType.migrations"/> parameter should be a function, which returns a list of migrations.
These migration functions will need to merge the migration functions returned from <DocLInk id="" section="" text="PersistableStateServices.getAllMigrations"/> with any migrations provided by the plugin.

Choose a reason for hiding this comment

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

DocLink id and section need to get filled in.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

those docs don't exist yet so i'll remove it

Choose a reason for hiding this comment

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

I'm talking about linking to the API docs for that function. Do the API docs need to be re-generated? If so, I can do that. I'm assuming the function exists, otherwise, we shouldn't be adding documentation recommending its usage. :)

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.

Left a few suggestions. I think having links to the referenced interfaces and links to examples of how it is used would be helpful.

## Exposing state that can be persisted but is not owned by plugin exposing it (registry)

Any plugin that owns collection of items whose state/configuration can be persisted should implement `PersistableStateService`
interface on their `setup` contract as well as make each item in the collection implement `PersistableStateDefinition` interface.
Copy link
Contributor

Choose a reason for hiding this comment

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

make each item in the collection implement PersistableStateDefinition interface.

Is it the plugin that is registering the item that will have to implement the PersistableStateDefinition interface on the item? Or is it the plugin that owns the collection?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

its the plugin providing the registry that defines how the items that are added to the registry look like

stores a bunch of embeddable panels input in its saved object and URL. Embeddable plugin setup contract implements `PersistableStateService`
interface and each `EmbeddableFactory` needs to implement `PersistableStateDefinition` interface.

note: if your plugin doesn't expose the state and is thus the only one storing state but still owning the registry
Copy link
Contributor

Choose a reason for hiding this comment

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

Might be worth rewording this to something like:

if your plugin doesn't expose state, then your plugin doesn't need to implement PersistableStateServiceinterface on thesetupcontract. If your plugin provide registration functionality for items it will not own the state for, the items should still implementPersistableStateDefinition`.

and reference extraction and injection methods correctly use the correct `PersistableStateService` implementation.

If a saved object contains state from another plugin, the <DocLink id="kibCoreSavedObjectsPluginApi" section="iaf33fb81-e64a-11eb-8631-9d6e17a74ca4" text-"SavedObjectType.migrations"/> parameter should be a function, which returns a list of migrations.
These migration functions will need to merge the migration functions returned from with any migrations provided by the plugin.
Copy link
Contributor

Choose a reason for hiding this comment

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

This sentence is a bit confusing to me. Is the These migration functions referring to the function parameter in the previous sentence or the list of migrations that the previous sentence is talking about?

Is this trying to say: the parameter function needs to call a call the plugin that owns the state it is trying to persistent and merge the result of that call into an array of migration functions with any migration logic that the parameter function will provide for state it also exposes?

An example might be helpful here.

If a saved object contains state from another plugin, the <DocLink id="kibCoreSavedObjectsPluginApi" section="iaf33fb81-e64a-11eb-8631-9d6e17a74ca4" text-"SavedObjectType.migrations"/> parameter should be a function, which returns a list of migrations.
These migration functions will need to merge the migration functions returned from with any migrations provided by the plugin.

For reference injection and extraction matching methods on PersistableStateService should be called and merged with plugins own array of references.
Copy link
Contributor

Choose a reason for hiding this comment

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

A code example here might be helpful.


### Storing persistable state as part of URL

When storing persistable state as part of URL you must make sure your URL is versioned. When loading the state `migrateToLatest` method
Copy link
Contributor

Choose a reason for hiding this comment

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

When storing persistable state as part of URL you must make sure your URL is versioned

Do we have suggestions on how to version the URL? Is it simply adding some field that has a version value in it?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

nothing, its completely up to the app how it does that.

### Storing persistable state as part of URL

When storing persistable state as part of URL you must make sure your URL is versioned. When loading the state `migrateToLatest` method
of `PersistableStateService` should be called, which will given the original version of state migrate it to latest.
Copy link
Contributor

Choose a reason for hiding this comment

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

of PersistableStateService should be called, which will given the original version of state migrate it to latest.

Maybe switch this to:

of PersistableStateService should be called, which will migrate the state from its original version to the latest.


### Migrations and Backward compatibility

As your plugin evolves, you may need to change your state in a breaking way. If that happens, you should write a migration to upgrade the any state that existed prior to the change.
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: the any -> the or any

migration to upgrade the any state that existed prior to the change. -> migration to upgrade the state that existed prior to the change.

@ppisljar ppisljar requested a review from a team as a code owner August 4, 2021 12:17
@ppisljar
Copy link
Contributor Author

ppisljar commented Aug 9, 2021

@elasticmachine merge upstream

Copy link

@stacey-gammon stacey-gammon left a comment

Choose a reason for hiding this comment

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

Some nits and links added, otherwise, LGTM

Co-authored-by: Stacey Gammon <gammon@elastic.co>
Copy link
Contributor

@jloleysens jloleysens 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 adding this Peter! I'm sure this will be a helpful reference for working with persistable state.

stores a bunch of embeddable panels input in its saved object and URL. Embeddable plugin setup contract implements `PersistableStateService`
interface and each `EmbeddableFactory` needs to implement `PersistableStateDefinition` interface.

Embeddable plugin exposes this interfaces:
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
Embeddable plugin exposes this interfaces:
Embeddable plugin exposes these interfaces:

Any plugin that stores any persistable state as part of their saved object should make sure that its saved object migration
and reference extraction and injection methods correctly use the matching `PersistableStateService` implementation for the state they are storing.

Take a look at [example saved object](https://github.com/elastic/kibana/blob/master/examples/embeddable_examples/server/searchable_list_saved_object.ts#L32) which stores an embeddable state. Note how the `migrations`, `extractReferences` and `injectReferences` are defined.
Copy link
Contributor

Choose a reason for hiding this comment

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

I followed this link (in the context of PR changes) and I did not see extractReferences or injectReferences there. I see this PR contains changes that introduce extract and inject in examples/embeddable_examples/public/migrations/migrations_embeddable_factory.ts. Is this what is being referred to here?

When storing persistable state as part of URL you must make sure your URL is versioned. When loading the state `migrateToLatest` method
of `PersistableStateService` should be called, which will migrate the state from its original version to latest.

note: Currently there is no recommended way on how to store version in url and its up to every application to decide on how to implement that.
Copy link
Contributor

@jloleysens jloleysens Aug 17, 2021

Choose a reason for hiding this comment

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

Are there some ways we specifically don't recommend plugins store the version in the URL. Like as a param in the path: /my-path/8.0.0/the-rest-of/my-path based on feedback we got on this point? (I'm thinking of things like product-level concerns).

Perhaps we can borrow the structure of the LocatorParams which has a containing object: { version: 'a.b.c', state } as our recommendation?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

we leave it completely up to the plugins how they want to do this.

@ppisljar
Copy link
Contributor Author

@elasticmachine merge upstream

@mistic mistic added v7.16.0 and removed v7.15.0 labels Aug 18, 2021
@ppisljar
Copy link
Contributor Author

ppisljar commented Sep 1, 2021

@elasticmachine merge upstream

@ppisljar ppisljar force-pushed the persistablestate/docs branch from f88c98b to a987ce9 Compare September 22, 2021 08:03
@kibanamachine
Copy link
Contributor

💚 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
kibanaUtils 404 407 +3
Unknown metric groups

API count

id before after diff
kibanaUtils 597 600 +3

History

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

@ppisljar ppisljar merged commit 3907d53 into elastic:master Sep 22, 2021
@stacey-gammon stacey-gammon added the auto-backport Deprecated - use backport:version if exact versions are needed label Sep 22, 2021
@kibanamachine
Copy link
Contributor

💚 Backport successful

Status Branch Result
7.x

This backport PR will be merged automatically after passing CI.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

auto-backport Deprecated - use backport:version if exact versions are needed DevDocs release_note:skip Skip the PR/issue when compiling release notes v7.16.0 v8.0.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[PersistableState] Improve documentation for how to use persistable state services

8 participants