-
Notifications
You must be signed in to change notification settings - Fork 59
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
Refactor Launch form to use a state machine #99
Conversation
Codecov Report
@@ Coverage Diff @@
## single-task-execution #99 +/- ##
=========================================================
+ Coverage 67.49% 67.71% +0.22%
=========================================================
Files 372 374 +2
Lines 6030 6078 +48
Branches 945 947 +2
=========================================================
+ Hits 4070 4116 +46
- Misses 1960 1962 +2
Continue to review full report at Codecov.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really like the approach of leveraging xstate more heavily!
src/components/Launch/LaunchWorkflowForm/LaunchWorkflowForm.tsx
Outdated
Show resolved
Hide resolved
export const launchMachine = Machine(launchMachineConfig, { | ||
actions: { | ||
setWorkflowVersion: assign((_, event) => ({ | ||
workflowVersion: (event as SelectWorkflowVersionEvent).workflowId |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a way we can cut back on the use of casting? I was looking at the docs for xstate and I understand they don't have 100% perfect typing throughout, but I was curious if there was anyway to use type narrowing on the event
passed in here or something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suspected you might bring this up :-).
I tried several approaches. I think the only real way to get solid type support is to use inline functions in the machine config. That didn't fully solve the problem and it's specifically recommend against by the documentation. So my compromise was to at least narrow things down by individually defining the events I was casting to so that in the context of the action we know what the shape of the data payload should look like.
I had a similar problem with the services
below here. I could not find a way with the current type definitions to make the return types of the services strongly types. At best, they will be Promise<any>
. That means that the implementations that I provide when I interpret this machine in my react hook have no way of being checked that they are returning a value with the correct shape, property names, etc.
The good news is that when the actions and services don't do what is expected, the tests will blow up. I spent a fair chunk of time getting tests working again, and some of that was finding places where actions/services were returning or expecting the wrong type. So I think for now, tests and runtime checking will be the best we can do.
I have two additional enhancements in mind for a follow-up PR:
- Look into model-based testing for the machine. This should ensure that all machine states are reachable, that the rendered components look correct when we reach each state, and should fully exercise all of the actions/services. That should be a good signal for when things change and our typing isn't able to warn us at compile time.
- Some people in the community have proposed workarounds involving runtime checks that are type guards. Basically, that we should be able to test the payload sent to the action and so a
is SelectWorkflowVersionEvent
. That won't help catch errors at compile-time though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess I really am that predictable that I'd bring up types in a PR 😆
Sounds good, I certainly have spent less time with xstate than you have, so thanks for the thoughtful comments and I'm glad we have validation here in the form of tests!
* refactor: make workflow details generic so it can be used for tasks (#96) * refactor: make workflow details generic so it can be used for tasks * chore: cleanup and moving tests over * feat: adding route and navigation to the task details page (#97) * Refactor Launch form to use a state machine (#99) * refactor: filling out details of the state machine for launch * refactor: checkpoint * refactor: mostly finished wiring of machine to component state * refactor: more work to get form component migrated to using machine * refactor: cleaning up state for selectors * fix: type error due to patch version upgrade * refactor: trying a flat state structure * fix: getting all tests passing again * chore: cleanup and docs * chore: pull request feedback * refactor: Make launch state and components generic (#100) * refactor: splitting launch machine into two separate types * refactor: move shared state out to component * refactor: use composition to create workflow form * refactor: update usage of LaunchWorkflowForm -> LaunchForm * chore: cleanup and fix tests * feat: Add Task support to Launch form (#101) * feat: add task support in launch components * test: updating launch form tests to handle task cases * fix: remaining broken tests * Cleanup work for launching single task executions. (#102) * feat: add support for launch tasks in entity details view * fix: correctly map initial parameters when relaunching * fix: correct parent name and back link in execution details page * fix: pass through referenceExecution when relaunching * test: check rendering of referenceExecution * test: adding tests for relaunch flow
# [0.13.0](http://github.com/lyft/flyteconsole/compare/v0.12.1...v0.13.0) (2020-10-08) ### Features * Improve UX for Single Task Executions ([#103](http://github.com/lyft/flyteconsole/issues/103)) ([d0335dc](http://github.com/lyft/flyteconsole/commit/d0335dc1f86b98b30011e63d686b8168262d3bbd)), closes [#96](http://github.com/lyft/flyteconsole/issues/96) [#97](http://github.com/lyft/flyteconsole/issues/97) [#99](http://github.com/lyft/flyteconsole/issues/99) [#100](http://github.com/lyft/flyteconsole/issues/100) [#101](http://github.com/lyft/flyteconsole/issues/101) [#102](http://github.com/lyft/flyteconsole/issues/102)
This migrates the state representations for
LaunchWorkflowForm
into a xstate state machine. Previously, a lot of logic and context variables were store inuseLaunchWorkflowFormState
. Now, all of the states in the flow are represented inlaunchMachine
, which is consumed by the state hook.The machine uses a handful of services to do the async work. These are provided by the state hook.
I also moved the state management for the workflow/launch plan selectors into a separate state hook. This is in preparation for making the launch form state generic enough to handle either a workflow or task as a source.
The net result of this should be no change in functionality.
Note: There are some TODOs left on this branch. This PR is against a feature branch, and I intend to address them in a follow-up PR.
launchMachine
, which includes state definitions for schema, context, events for the whole launch flow. It also exports a machine config and a machine instance to be consumed by an interpreter.useLaunchWorkflowFormState
. It now only contains theservices
used by the state machine for loading workflows, launch plans, and inputs. It also wires the state machine context into a child instance of auseWorkflowSourceSelectorState
hook.useWorkflowSourceStateSelector
hook, which translates between state machine context and the props/states needed for our SearchableSelector component.LaunchWorkflowForm
to use state-matching for conditional rendering of elements, and to consume the various context variables from our state machine.devTools
option, which should betrue
in development.xstate/react
to fix an issue with typings onuseMachine