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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: subscription leakage in ReactiveCommand #1218

Merged
merged 2 commits into from Jan 4, 2017

Conversation

Hinidu
Copy link
Contributor

@Hinidu Hinidu commented Dec 19, 2016

Hi! I've described my issue today on the slack channel but nobody replies to me so I found the problem myself 馃槃 That's my original message:

[SlackMessage]
Hello everyone! I have a problem: the ViewModel is leaking if I use any property of the Model inside canExecute argument of any ReactiveCommand. The Model lives for the entire life of the application but ViewModel should be removed when I close its tab. I use RxUI 7.0. The example:

var canDeepCopy = this.WhenAnyValue(vm => vm.Model.Id).Select(id => id != Constants.NewEntityId);
this.DeepCopy = ReactiveCommand.Create(this.HandleDeepCopy, canDeepCopy);

If I replace canDeepCopy value by Observable.Return(true) ViewModel is not leaking anymore. I even tried to dispose DeepCopy command but it didn't give any results. By the way I have another command in this ViewModel which doesn't use the Model inside its canExecute and this command doesn't cause the leakage of the ViewModel.
My application is written in WPF.
I can't find any information whether I should dispose reactive commands or not.
https://docs.reactiveui.net/en/design-guidelines/use-this-on-left-of-whenany.html Here I found that there can be the problems if lifetime of the object on which we call WhenAny is longer than lifetime of our object. But there is no info about whether it cause the problems if I use such long-life dependency inside the expression argument of WhenAny.
[/SlackMessage]

The actual problem was the leakage of subscription to canExecute. There are two subscriptions and I don't know why do we need the second one so I just removed it. But the first one which do the actual work is not disposed so I fixed it. I've tested these changes in my project and everything works fine now.

Remove the unneeded subscription and dispose the right one.
@ghuntley
Copy link
Member

Suggested reviewer(s): @kentcb

@Hinidu
Copy link
Contributor Author

Hinidu commented Dec 19, 2016

By the way in addition to the proposed change to fix my issue I've disposed the command when View was deactivated. Without disposing the ViewModel was leaking as before.

@shiftkey
Copy link
Contributor

Yep, I'm not sure there's a good reason for the dual-subscription here.

Tracing back through the history, initially the disposable was created with some callback logic. Then it was moved out into en empty subscription as part of introducing more functionality, before it became the current ReactiveCommand behaviour in v7.

It really only makes sense to have one subscription here (it seems important). I'll let @kentcb confirm this but i'm 馃憤 on this change...

@Hinidu
Copy link
Contributor Author

Hinidu commented Dec 20, 2016

@shiftkey thank you for review! By the way commits referenced by you contain only one subscription. So the second one was added later.

@Hinidu
Copy link
Contributor Author

Hinidu commented Dec 20, 2016

The subscription which wasn't disposed was added here.
Perhaps we could add a test that checks that canExecute is properly unsubscribed after the ReactiveCommand disposal.

@Hinidu
Copy link
Contributor Author

Hinidu commented Dec 20, 2016

I've committed the test to assure that canExecute is unsubscribed after ReactiveCommand disposal.

@Hinidu
Copy link
Contributor Author

Hinidu commented Dec 20, 2016

I've checked that the previous version is failing this test.

@Hinidu
Copy link
Contributor Author

Hinidu commented Dec 30, 2016

@kentcb ping

@kentcb
Copy link
Contributor

kentcb commented Dec 30, 2016

@Hinidu am aware, and planning to look at this next week when I'm no longer on holidays.

@Hinidu
Copy link
Contributor Author

Hinidu commented Dec 30, 2016

@kentcb Thanks! Our holidays in Russia will start tomorrow but I will try to respond if you will have any questions.

@kentcb
Copy link
Contributor

kentcb commented Jan 4, 2017

Definitely an oops, this one. Thanks for chasing it down @Hinidu and for submitting a great PR 馃憤

@ghuntley ghuntley changed the title Fix subscription leakage in ReactiveCommand fix: subscription leakage in ReactiveCommand Jan 4, 2017
@ghuntley ghuntley added this to the 7-vNext milestone Jan 4, 2017
@ghuntley
Copy link
Member

ghuntley commented Jan 4, 2017

Thanks for your patience @Hinidu. This has been merged in and is now available from our MyGet alpha channel. We are looking at doing a new release in a couple days time and this will be included within - it will either be 7.0.1 or 7.1.0 depending on how some other reviews progress.

@ghuntley ghuntley merged commit 9a56f30 into reactiveui:develop Jan 4, 2017
@Hinidu
Copy link
Contributor Author

Hinidu commented Jan 4, 2017

Thanks @kentcb abd @ghuntley! I'm on holidays until next monday so I can wait :-)

@Hinidu Hinidu deleted the patch-2 branch January 4, 2017 09:11
@lock lock bot locked and limited conversation to collaborators Jun 26, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants