🌊 Refactor API control flow for stream management#211696
🌊 Refactor API control flow for stream management#211696miltonhultgren merged 88 commits intoelastic:mainfrom
Conversation
x-pack/platform/plugins/shared/streams/server/lib/streams/state_management/types.ts
Outdated
Show resolved
Hide resolved
x-pack/platform/plugins/shared/streams/server/lib/streams/state_management/types.ts
Outdated
Show resolved
Hide resolved
x-pack/platform/plugins/shared/streams/server/lib/streams/state_management/types.ts
Outdated
Show resolved
Hide resolved
x-pack/platform/plugins/shared/streams/server/lib/streams/state_management/state.ts
Outdated
Show resolved
Hide resolved
x-pack/platform/plugins/shared/streams/server/lib/streams/state_management/state.ts
Outdated
Show resolved
Hide resolved
x-pack/platform/plugins/shared/streams/server/lib/streams/state_management/wired_stream.ts
Outdated
Show resolved
Hide resolved
x-pack/platform/plugins/shared/streams/server/lib/streams/state_management/wired_stream.ts
Outdated
Show resolved
Hide resolved
x-pack/platform/plugins/shared/streams/server/lib/streams/state_management/wired_stream.ts
Outdated
Show resolved
Hide resolved
x-pack/platform/plugins/shared/streams/server/lib/streams/client.ts
Outdated
Show resolved
Hide resolved
x-pack/platform/plugins/shared/streams/server/lib/streams/state_management/wired_stream.ts
Outdated
Show resolved
Hide resolved
x-pack/platform/plugins/shared/streams/server/lib/streams/state_management/types.ts
Outdated
Show resolved
Hide resolved
x-pack/platform/plugins/shared/streams/server/lib/streams/state_management/wired_stream.ts
Outdated
Show resolved
Hide resolved
x-pack/platform/plugins/shared/streams/server/lib/streams/state_management/state.ts
Outdated
Show resolved
Hide resolved
…table helper for State, fix bugs, split validation
|
This looks mostly good to me, one thing I found is the following: When trying to create a classic stream that doesn't exist as data stream, it fails super late: Returns What about adding something to the upsert validation that checks whether the underlying datastream exists if Love the separate validation hooks btw, much easier to follow. |
| const existsInStartingState = startingState.has(this._definition.name); | ||
|
|
||
| if (!existsInStartingState) { | ||
| // TODO in this check, make sure the existing data stream is not a stream-created one (if it is, state might be out of sync, but we can fix it) |
There was a problem hiding this comment.
should we still do this? I think I put this here, it's about if the data stream exists but we created it, then it's probably fine to "grandfather" it in. But we also can not do this for now
There was a problem hiding this comment.
I'll skip it for now
.../platform/plugins/shared/streams/server/lib/streams/state_management/streams/wired_stream.ts
Outdated
Show resolved
Hide resolved
| desiredState: State, | ||
| startingState: State | ||
| ): Promise<ValidationResult> { | ||
| return { isValid: true, errors: [] }; |
There was a problem hiding this comment.
Just a note: This makes me think adding the "force=false" query param is not the only change we need to do - here the validation hook relies on the cascading changes doing its thing, which is probably OK for now, but we will need to check through all the validation logic whether it relies on it this way.
|
@flash1293 Added the validation to the upsert of UnwiredStream |
flash1293
left a comment
There was a problem hiding this comment.
LGTM after the last round of testing.
Only thing I'm not sure about is the block list in updateOrRolloverDataStream - would be great to get feedback from the ES team on that.
💚 Build Succeeded
Metrics [docs]Public APIs missing comments
Unknown metric groupsAPI count
ESLint disabled in files
Total ESLint disabled count
History
|
|
Starting backport for target branches: 8.x https://github.com/elastic/kibana/actions/runs/14331874800 |
💔 All backports failed
Manual backportTo create the backport manually run: Questions ?Please refer to the Backport tool documentation |
Manual backport of #211696 --------- Co-authored-by: Joe Reuter <johannes.reuter@elastic.co> Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
Background
This PR is a proposal for a different way to structure the Streams code flow based on some challenges faced while working on https://github.com/elastic/streams-program/issues/26 and discussed here and here, mainly around finding it difficult to decide where to place certain validations that need access to the state as a whole.
It is also in response to some expressed difficulty about how to add new stream types into the code base.
It aims to achieve 3 goals:
In the future, this will most likely be handled by Elasticsearch to a large degree, as imagined in https://github.com/elastic/streams-program/discussions/30
The solution takes inspiration from the reconciliation / controller pattern that Kubernetes uses, where users specify a desired state and the system takes action towards reaching that step. But it is also somewhat more similar to how React's Virtual DOM works in that it happens in a single iteration.
Another key pattern is the Active Record pattern, we let each stream class contain all the logic for how to validate and modify that stream in Elasticsearch. The client and
Stateclass simply orchestrate the flow but defer all actual work and decision making to the stream classes.Note: This PoC ignores the management of assets
Summary
The process takes the following steps:
StreamChangeobjects before passing these toState.applyChangesmethod (which also takes a toggle for dry runs)StateclassExecutionPlanclass which does planning (mainly for actions around Unwired streams) and then handles executing the actions in the most parallel way but in the safe orderThis PR also changes our
resyncendpoint to make use of the same rough strategy (load current state, mark all as created, get Elasticsearch actions and apply).[1] Applying changes:
streamFromDefinitionwhich is the only mapping between the definition documents and the Active Record-style stream type classesAdding new stream types
Key in all of this is that the client and
Stateclasses don't know anything about any of the specific stream types, they know only of theStreamActiveRecordinterface.When adding a new stream type you need to implement this interface and update
streamFromDefinitionto create the right class for your new definition. Streams of different types should only interact with each other by creating cascading changes.Possible follow up tasks
attemptChangespass back theDesiredStateand plannedElasticsearchActionsas debug information based on a flag (maybe also all cascading changes)attemptChangesandresyncwith the new LockManager [Obs AI Assistant] Distributed lock manager #216397Out of scope