Merge lp:~jeremywootten/appcenter/fix-1617687-multiple-updates into lp:~elementary-apps/appcenter/appcenter

Proposed by Jeremy Wootten
Status: Merged
Approved by: Danielle Foré
Approved revision: 293
Merged at revision: 324
Proposed branch: lp:~jeremywootten/appcenter/fix-1617687-multiple-updates
Merge into: lp:~elementary-apps/appcenter/appcenter
Diff against target: 243 lines (+116/-30)
4 files modified
src/Application.vala (+26/-8)
src/Core/Client.vala (+88/-20)
src/MainWindow.vala (+1/-1)
src/Views/AppListView.vala (+1/-1)
To merge this branch: bzr merge lp:~jeremywootten/appcenter/fix-1617687-multiple-updates
Reviewer Review Type Date Requested Status
Adam Bieńkowski (community) code / testing Needs Fixing
Review via email: mp+305253@code.launchpad.net

Commit message

Prevents multiple authentication dialogs on resume from suspend by preventing more than one update_cache timeout at a time.

Description of the change

Prevents multiple authentication dialogs on resume from suspend by preventing more than one update_cache timeout at a time.

To post a comment you must log in.
Revision history for this message
Adam Bieńkowski (donadigo) wrote :

Tested it two times, unfortunately it doesn't fix the issue for me. However, it does display the warning that the update_cache was called when there is an on-going timeout. I guess we probably need to return at the end of the update_cache_timeout_id statement block?

review: Needs Fixing (code / testing)
Revision history for this message
Jeremy Wootten (jeremywootten) wrote :

OK - sorry it didnt fix it - will think again.

Revision history for this message
Danielle Foré (danrabbit) wrote :

I can confirm (with Adam) that this reduces the number of dialogs to 1, which is a massive improvement. I think we agree though that it still feels weird to get a root password prompt at resume time and we probably should just not show the dialog and let it wait for the next refresh while logged in

293. By Jeremy Wootten

Delay cache update after network up and do not force

Revision history for this message
Matt Spaulding (madsa) wrote :

This fix seems to work pretty good for me, but isn't a complete fix. If I resume my laptop from suspend and wait at the login screen for some period of time then I'll still see the authentication dialog. Couldn't you query DBus to check if the screen is locked? It looks like light-locker supports a GetActive method that would allow you to do that.

Revision history for this message
Jeremy Wootten (jeremywootten) wrote :

Yes, I knew this was a quick, incomplete, fix but I have not had time to fid out the details of how to check whether the screen is locked yet and implement it.

Revision history for this message
Danielle Foré (danrabbit) wrote :

Since this is an often-reported pain point for users right now, and this branch does offer an improvement from the behavior of trunk, I'm inclined to say we should merge in order to get this fix in the next and make a bug report targeted to the next milestone about how to improve this block of code, if Jeremy doesn't have the time to make those changes at the moment.

Revision history for this message
Danielle Foré (danrabbit) wrote :

in the next release*

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/Application.vala'
2--- src/Application.vala 2016-08-23 14:35:57 +0000
3+++ src/Application.vala 2016-10-05 13:51:22 +0000
4@@ -23,6 +23,8 @@
5 { null }
6 };
7
8+ private const int SECONDS_AFTER_NETWORK_UP = 60;
9+
10 public static bool show_updates;
11 public static bool silent;
12 MainWindow main_window;
13@@ -59,13 +61,10 @@
14 var client = AppCenterCore.Client.get_default ();
15 if (silent) {
16 NetworkMonitor.get_default ().network_changed.connect ((available) => {
17- if (available) {
18- client.update_cache.begin (true);
19- }
20+ schedule_cache_update (!available);
21 });
22
23- client.update_cache.begin ();
24-
25+ client.update_cache.begin (true);
26 silent = false;
27 hold ();
28 return;
29@@ -84,11 +83,30 @@
30 if (show_updates) {
31 main_window.go_to_installed ();
32 }
33+ }
34+
35+ main_window.present ();
36+ }
37+
38+ private uint cache_update_timeout_id = 0;
39+ private void schedule_cache_update (bool cancel = false) {
40+ var client = AppCenterCore.Client.get_default ();
41+
42+ if (cache_update_timeout_id > 0) {
43+ Source.remove (cache_update_timeout_id);
44+ cache_update_timeout_id = 0;
45+ }
46+
47+ if (cancel) {
48+ client.cancel_updates (true); // Also stops timeouts.
49+ return;
50 } else {
51- client.interface_cancellable.reset ();
52+ cache_update_timeout_id = Timeout.add_seconds (SECONDS_AFTER_NETWORK_UP, () => {
53+ client.update_cache.begin ();
54+ cache_update_timeout_id = 0;
55+ return false;
56+ });
57 }
58-
59- main_window.present ();
60 }
61 }
62
63
64=== modified file 'src/Core/Client.vala'
65--- src/Core/Client.vala 2016-09-24 01:53:02 +0000
66+++ src/Core/Client.vala 2016-10-05 13:51:22 +0000
67@@ -27,9 +27,13 @@
68 private Gee.LinkedList<AppCenter.Task> task_with_agreement_list;
69 private Gee.HashMap<string, AppCenterCore.Package> package_list;
70 private AppStream.Database appstream_database;
71- public GLib.Cancellable interface_cancellable;
72+ private GLib.Cancellable interface_cancellable;
73 private GLib.DateTime last_cache_update;
74 private uint updates_number = 0U;
75+ private uint update_cache_timeout_id = 0;
76+ private bool refresh_in_progress = false;
77+
78+ private const int SECONDS_BETWEEN_REFRESHES = 60*60*24;
79
80 private Client () {
81 try {
82@@ -49,6 +53,7 @@
83 task_with_agreement_list = new Gee.LinkedList<AppCenter.Task> ();
84 package_list = new Gee.HashMap<string, AppCenterCore.Package> (null, null);
85 interface_cancellable = new GLib.Cancellable ();
86+ last_cache_update = null;
87
88 appstream_database = new AppStream.Database ();
89 try {
90@@ -340,12 +345,12 @@
91 return package;
92 }
93
94- public async void refresh_updates () {
95+ private async void refresh_updates () {
96 var update_task = new AppCenter.Task ();
97 updating_cache = true;
98
99 try {
100- Pk.Results result = yield update_task.get_updates_async (0, null, (t, p) => {});
101+ Pk.Results result = yield update_task.get_updates_async (0, interface_cancellable, (t, p) => {});
102 bool was_empty = updates_number == 0U;
103 updates_number = get_package_count (result.get_package_array ());
104 if (was_empty && updates_number != 0U) {
105@@ -368,7 +373,9 @@
106 } catch (Error e) {
107 critical (e.message);
108 }
109+
110 updating_cache = false;
111+ refresh_in_progress = false;
112 }
113
114 public uint get_package_count (GLib.GenericArray<weak Pk.Package> package_array) {
115@@ -391,24 +398,85 @@
116 return size;
117 }
118
119+ public void cancel_updates (bool cancel_timeout) {
120+ interface_cancellable.cancel ();
121+
122+ if (update_cache_timeout_id > 0 && cancel_timeout) {
123+ Source.remove (update_cache_timeout_id);
124+ update_cache_timeout_id = 0;
125+ last_cache_update = null;
126+ }
127+
128+ interface_cancellable = new GLib.Cancellable ();
129+ refresh_in_progress = false;
130+ }
131+
132 public async void update_cache (bool force = false) {
133- // One cache update a day, keeps the doctor away!
134- if (force || last_cache_update == null || (new DateTime.now_local ()).difference (last_cache_update) >= GLib.TimeSpan.DAY) {
135- var refresh_task = new AppCenter.Task ();
136- try {
137- yield refresh_task.refresh_cache_async (false, null, (t, p) => { });
138- last_cache_update = new DateTime.now_local ();
139- } catch (Error e) {
140- critical (e.message);
141- }
142-
143- refresh_updates.begin ();
144- }
145-
146- GLib.Timeout.add_seconds (60*60*24, () => {
147- update_cache.begin ();
148- return GLib.Source.REMOVE;
149- });
150+ debug ("update cache called %s", force.to_string ());
151+ bool success = false;
152+
153+ /* Make sure only one update cache can run at a time */
154+ if (refresh_in_progress) {
155+ debug ("Update cache already in progress - returning");
156+ return;
157+ } else {
158+ refresh_in_progress = true;
159+ }
160+
161+
162+ if (update_cache_timeout_id > 0) {
163+ if (force) {
164+ debug ("Forced update_cache called when there is an on-going timeout - cancelling timeout");
165+ Source.remove (update_cache_timeout_id);
166+ update_cache_timeout_id = 0;
167+ } else {
168+ debug ("Refresh timeout running and not forced - returning");
169+ refresh_in_progress = false;
170+ return;
171+ }
172+ }
173+
174+ /* One cache update a day, keeps the doctor away! */
175+ if (force || last_cache_update == null ||
176+ (new DateTime.now_local ()).difference (last_cache_update) / GLib.TimeSpan.SECOND >= SECONDS_BETWEEN_REFRESHES) {
177+
178+ var nm = NetworkMonitor.get_default ();
179+
180+ if (nm.get_network_available()) {
181+ debug ("New refresh task");
182+ var refresh_task = new AppCenter.Task ();
183+
184+
185+ try {
186+ Pk.Results result = yield refresh_task.refresh_cache_async (false, interface_cancellable, (t, p) => { });
187+ success = result.get_exit_code () == Pk.Exit.SUCCESS;
188+ last_cache_update = new DateTime.now_local ();
189+ } catch (Error e) {
190+ critical ("Update_cache: Refesh cache async failed - %s", e.message);
191+
192+ }
193+
194+ if (success) {
195+ refresh_updates.begin ();
196+ }
197+
198+ } else {
199+ refresh_in_progress = false; //Stops new timeout while no network.
200+ }
201+ } else {
202+ debug ("Too soon to refresh and not forced");
203+ }
204+
205+
206+ if (refresh_in_progress) {
207+ update_cache_timeout_id = GLib.Timeout.add_seconds (SECONDS_BETWEEN_REFRESHES, () => {
208+ update_cache_timeout_id = 0;
209+ update_cache.begin (true);
210+ return GLib.Source.REMOVE;
211+ });
212+
213+ refresh_in_progress = success;
214+ } // Otherwise updates and timeout were cancelled during refresh, or no network present.
215 }
216
217 public async Gee.TreeSet<Pk.Package> get_installed_packages () {
218
219=== modified file 'src/MainWindow.vala'
220--- src/MainWindow.vala 2016-09-07 18:38:31 +0000
221+++ src/MainWindow.vala 2016-10-05 13:51:22 +0000
222@@ -163,7 +163,7 @@
223 }
224 });
225
226- client.interface_cancellable.cancel ();
227+ client.cancel_updates (false); //Timeouts keep running
228 return true;
229 }
230
231
232=== modified file 'src/Views/AppListView.vala'
233--- src/Views/AppListView.vala 2016-09-17 19:28:03 +0000
234+++ src/Views/AppListView.vala 2016-10-05 13:51:22 +0000
235@@ -250,7 +250,7 @@
236 uint update_numbers = 0U;
237 uint64 update_real_size = 0ULL;
238 foreach (var package in get_packages ()) {
239- if (package.state == AppCenterCore.Package.State.UPDATE_AVAILABLE) {
240+ if (package.update_available) {
241 update_numbers++;
242 update_real_size += package.change_information.get_size ();
243 }

Subscribers

People subscribed via source and target branches