Skip to content
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

[API] Changes to mutation API #3483

Merged
merged 45 commits into from
Jan 17, 2021
Merged

[API] Changes to mutation API #3483

merged 45 commits into from
Jan 17, 2021

Conversation

akhenry
Copy link
Contributor

@akhenry akhenry commented Oct 31, 2020

Changes how object mutation works behind the scenes in order to keep objects in sync automatically when their model changes.

  • The way that objects are mutated and observed has not changed, openmct.objects.mutate and openmct.objects.observe should still be used in the same way that they were before.
  • Behind the scenes, domain objects that are mutable are wrapped in a new MutableDomainObject that exposes mutator and observer functions that allow objects to be mutated in such a way that all instances can be kept in sync.
  • It is now possible to retrieve MutableDomainObjects from the API, instead of regular domain objects. These are automatically updated when mutation occurs on any instance of the object, replacing the need for "*" listeners. Note that the view API now provides objects in this form by default. Therefore, you do not need to do anything differently in views, the domain objects will just magically keep themselves up to date.
  • If for some reason you need to retrieve an object manually via openmct.objects.get (you should ask why you need to do this) and you want it to magically keep itself in sync, there is a new API function named openmct.objects.getMutable(identifier). Note that if you do this you will be responsible for the object's lifecycle. It relies on listeners which must be destroyed when the object is no longer needed, otherwise memory leaks will occur. You can destroy a MutableDomainObject and its (internal) listeners by calling openmct.objects.destroyMutable(mutableDomainObject). Any listeners created by calls to openmct.objects.observe need to be cleaned up separately.
  • If the composition of a MutableDomainObject is retrieved using the Composition API, all children will be returned as MutableDomainObjects automatically. Their lifecycle will be managed automatically, and is tied to the lifecycle of the parent.
  • Any MutableDomainObject provided by the Open MCT framework itself (eg. provided to view providers by the View API, or from the composition API) will have its lifecycle managed by Open MCT, you don't need to worry destroying it.
  • Some instances of "*" observers have been now been replaced. Due to time constraints I was unable to replace all of them, so I will file followup issues to address them.
  • There were (and still are) a large number of views where we are tracking multiple instances of the same domain object (usually named things like observedDomainObject, internalDomainObject, etc.). I have removed these wherever I have changed view code, but there are still a lot of examples of this in our codebase. We should avoid having multiple different instances of the same domain object in the same view, it's very confusing to developers. This was I think partly necessitated by the need to use "*" observers, so hopefully we won't need to do it going forward.

TL;DR

  • "*" observers are no longer needed anywhere. In views, the domain object provided to the view provider will automatically be kept in sync, so if the domain object is a reactive Vue property (eg. it's passed in via props) then Vue reactivity will take care of updating the view automatically.
  • If for some reason you need to manually retrieve a MutableDomainObject (ie. an automatically synchronized version of a domain object) you can use openmct.objects.getMutable(identifier). However, you will be responsible for destroying it.

Note: I updated the Object API to be an ES6 module. This was necessitated by a weird issue in Webpack with using a mixture of require and ES6 imports that I could not resolve using the usual .default fix. This resulted the indentation of the whole file shifting, which means every line shows up as changed in the diff unless you use the Hide whitespace changes option in the File Changes tab.

To do:

@akhenry akhenry changed the title Mutation update [API] Changes to mutation API Oct 31, 2020
@@ -26,7 +26,7 @@
class="js-lad-table__body__row"
@contextmenu.prevent="showContextMenu"
>
<td class="js-first-data">{{ name }}</td>
<td class="js-first-data">{{ domainObject.name }}</td>
Copy link
Contributor Author

Choose a reason for hiding this comment

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

domainObject provided by view API is now automatically kept in sync, so I can just use Vue reactivity to update the name when it changes. No need for any event listeners at all.

@akhenry
Copy link
Contributor Author

akhenry commented Dec 22, 2020

Well, that was a Homeric epic.

I believe I have addressed all of the review comments, merged from master, and fixed the infinity bugs that came out of it.

@akhenry
Copy link
Contributor Author

akhenry commented Dec 23, 2020

Oops, missed one feedback comment. Fixed now.

@shefalijoshi
Copy link
Contributor

@akhenry
I think the changes look good, but I'm not sure what you meant by this comment. Which view API are you talking about here?
Note that the view API now provides objects in this form by default. Therefore, you do not need to do anything differently in views, the domain objects will just magically keep themselves up to date.

@akhenry
Copy link
Contributor Author

akhenry commented Jan 9, 2021

I think the changes look good, but I'm not sure what you meant by this comment. Which view API are you talking about here?
Note that the view API now provides objects in this form by default. Therefore, you do not need to do anything differently in views, the domain objects will just magically keep themselves up to date.

@shefalijoshi The Open MCT View API. View providers are now supplied with a MutableDomainObject to their view function instead of a regular DomainObject. Because the lifecycle of a view is well defined Open MCT itself can manage the destruction of the MutableDomainObject that it provides to views, so that the views themselves don't need to worry about it.

@shefalijoshi
Copy link
Contributor

@akhenry please resolve conflict so we can merge this.

@akhenry
Copy link
Contributor Author

akhenry commented Jan 16, 2021

@shefalijoshi Done!

@akhenry akhenry dismissed shefalijoshi’s stale review January 16, 2021 01:02

Merge conflicts resolved

Copy link
Contributor

@davetsay davetsay left a comment

Choose a reason for hiding this comment

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

LGTM

Reviewer Checklist

Changes appear to address issue? Y
Appropriate unit tests included? Y
Code style and in-line documentation are appropriate? Y
Commit messages meet standards? Y
Has associated issue been labelled unverified? Y

@davetsay davetsay merged commit 92737b4 into master Jan 17, 2021
@davetsay davetsay deleted the mutation-update branch January 17, 2021 22:15
@davetsay
Copy link
Contributor

@akhenry , merged, but can you provide an issue with testing instructions?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants