-
Notifications
You must be signed in to change notification settings - Fork 8.3k
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
[discuss] Plugin / SavedObjects architecture #72028
Comments
@streamich Let me know if I missed anything from our conversation. |
Pinging @elastic/kibana-platform (Team:Platform) |
There are many ways to solve these architectural problems. But I wonder long-term if this pattern of using the "database" directly from the browser and the auto-generated CRUD API is suitable for plugins with complex domains. It feels like it's a big enabler for getting started while a plugin and it's domain is small, but could become hard to maintain and inflexible as the plugin grows and it's domain starts to become more and more complex. |
While working on SO Tagging, I came to very similar observations. Overall, the generic SO http apis are not really suited for domain-based endpoints. Most obvious reasons being:
There was, at some point, per-attribute validation for SO in the legacy platform. We removed it however when we migrated, because there was no (as zero) usages of it. Also this validation system was very basic. It only allowed per field synchronous and static validation, which is just not good enough for any complex validation needs.
We discussed it a bit with @kobelb, and my opinion on the subject is quite simple: If these generic SO apis that are capable of handling all SO types in a raw format probably made sense initially, it just doesn't scale or work anymore. First proof of that would be the multiplication of the If the Also, Overall, I think that these generic SO API don't really make sense anymore, and that we should get away from them. The route/APIs I think are 'dangerous' and should be removed (or at least kept internal for some, see the SO management comment lower) from the 'generic' SO HTTP API are, to be changed for per-type routes instead are:
There are some routes / API that intrinsically requires to be 'generic' and work with raw SO structure, and that would remain unchanged:
Note: The SO management section, by nature, would still need to have access to some of these generic APIs ( Question: Are there other cases where these API would still requires to work for multiple type? Are we, anywhere in the code, performing batch operations on multiple types at the same time for example? The most controversial route now: What tools could
|
When saved-objects have references to each other, this can introduce some complexities because developers would have to use the specialized clients to |
TBH I would include that in the goals of these changes. For example for Note that even long term, I don't see the current SO APIs being removed from the server-side, meaning that a custom client for a type having various kind of references would still be able to use bulk_get or find under the hood. But removing the http endpoints would 'force' SO API consumers to migrate to this new design. |
I'm glad to report that all browser plugins are now using dedicated domain based APIs. In #174497 we're working on exposing dedicated public APIs for the last saved object types. As such I think we've addressed the architectural shortcomings identified in this issue 🥳 |
SavedObjects are typically used as follows:
This pattern leads to an architecture with several drawbacks:
1. Business logic is embedded in React components
When React components directly call the SavedObjectsClient it means all business logic lives in these components themselves. This can make it hard to understand the business logic and makes it harder to test.
Moving the business logic out of components can be done in several ways:
2. It's impossible to share business logic between the browser and server
Plugins often have a need to enforce the same business logic on the browser and server. Subtle differences in the browser and server SavedObjectsClient makes it impossible to write a common abstraction.
3. The SavedObjects HTTP API cannot maintain backwards compatibility in minors
Because all of a plugin's Saved Object types and all their fields forms part of the API, it's impossible for plugins to insert an abstraction layer to maintain backwards compatibility while evolving how that plugin's state gets persisted. (Through migrations, the API can successfully migrate outdated documents before writing them, but this is only one way. It's not possible for consumers who only understand the outdated fields to continue to read from the API). This means that even though the API routes and methods are stable, more complex integrations that read from and transform Saved Object attributes are likely to break in every minor.
4. The SavedObjects HTTP API is "dangerous" for users to integrate with
Because the HTTP API doesn't apply any business logic or validation, users integrating with this API can easily create invalid Saved Objects. This can lead to an integration which seems to work, but when a user later tries to use a feature in Kibana that feature unexpectedly fails. Coupled with the fact that there can be breaking changes in a minor when reading from the API (see (3)), this can cause integrations to silently start failing after an upgrade.
5. The SavedObjects HTTP API is unintuitive for users to integrate with
SavedObjects are designed primarily around the requirements of the persistence layer (and to some extent the security layer, since security can only be applied on an per object-type level). This can lead to a "persistence model" that doesn't have an intuitive mapping to the Plugin's domain.
Kibana's Alerts HTTP API is a nice example of an API that exposes the domain.
kibana/x-pack/plugins/alerts/README.md
Lines 30 to 32 in ce45dad
Although it's possible to emulate the behaviour of
POST /api/alerts/alert/{id}/_unmute_all
with the SavedObjects HTTP API this would be much more work to implement for a user and importantly won't capture the domain language that allow users to relate domain concepts to API actions.(Note I'm not trying to argue that all API's should avoid CRUD on Restful resources in favour of an RPC-like API)
Although Plugins are able to still provide an additional API as an alternative to the auto-generated SavedObjects API, in practise this rarely happens.
The text was updated successfully, but these errors were encountered: