Merge lp:~mardy/account-polld/no-account-watching into lp:~ubuntu-push-hackers/account-polld/trunk

Proposed by Alberto Mardegan
Status: Merged
Approved by: Jonas G. Drange
Approved revision: 177
Merged at revision: 174
Proposed branch: lp:~mardy/account-polld/no-account-watching
Merge into: lp:~ubuntu-push-hackers/account-polld/trunk
Diff against target: 513 lines (+94/-150)
7 files modified
accounts/account-watcher.c (+53/-93)
accounts/account-watcher.h (+5/-3)
accounts/accounts.c (+2/-2)
accounts/accounts.go (+12/-8)
cmd/account-polld/account_service.go (+11/-13)
cmd/account-polld/main.go (+10/-28)
cmd/account-watcher-test/main.go (+1/-3)
To merge this branch: bzr merge lp:~mardy/account-polld/no-account-watching
Reviewer Review Type Date Requested Status
Jonas G. Drange (community) Approve
system-apps-ci-bot continuous-integration Approve
Review via email: mp+300847@code.launchpad.net

Commit message

Don't watch accounts for changes: retrieve a new list at every poll

Watching for account changes makes the code more complicated than needed: we can simply query the list of enabled accounts at every Poll cycle, and check the differences with the previous list. This avoids the need to setup account watches and, more importantly, requires only once instance of AgAccountManager (compared to one instance for each service type).

Also, simplify the configuration of supported services: drop the usage of the "service type" concept, and rely on the service IDs only; this makes account-polld much easier to extend.

Description of the change

Don't watch accounts for changes: retrieve a new list at every poll

Watching for account changes makes the code more complicated than needed: we can simply query the list of enabled accounts at every Poll cycle, and check the differences with the previous list. This avoids the need to setup account watches and, more importantly, requires only once instance of AgAccountManager (compared to one instance for each service type).

Also, simplify the configuration of supported services: drop the usage of the "service type" concept, and rely on the service IDs only; this makes account-polld much easier to extend.

To post a comment you must log in.
Revision history for this message
system-apps-ci-bot (system-apps-ci-bot) wrote :

PASSED: Continuous integration, rev:177
https://jenkins.canonical.com/system-apps/job/lp-account-polld-ci/13/
Executed test runs:
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build/1029
    SUCCESS: https://jenkins.canonical.com/system-apps/job/test-0-autopkgtest/label=phone-armhf,release=vivid+overlay,testname=default/197
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-0-fetch/1029
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=vivid+overlay/926
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=xenial+overlay/926
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=yakkety/926
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=vivid+overlay/920
        deb: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=vivid+overlay/920/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=xenial+overlay/920
        deb: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=xenial+overlay/920/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=yakkety/920
        deb: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=yakkety/920/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=vivid+overlay/920
        deb: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=vivid+overlay/920/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=xenial+overlay/920
        deb: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=xenial+overlay/920/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=yakkety/920
        deb: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=yakkety/920/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=vivid+overlay/920
        deb: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=vivid+overlay/920/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=xenial+overlay/920
        deb: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=xenial+overlay/920/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=yakkety/920
        deb: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=yakkety/920/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://jenkins.canonical.com/system-apps/job/lp-account-polld-ci/13/rebuild

review: Approve (continuous-integration)
Revision history for this message
Jonas G. Drange (jonas-drange) wrote :

Wonderful, thanks. Will you let me know when there's a silo for this, I'd like to see how it works.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'accounts/account-watcher.c'
2--- accounts/account-watcher.c 2016-04-19 19:58:25 +0000
3+++ accounts/account-watcher.c 2016-07-22 08:01:34 +0000
4@@ -31,13 +31,10 @@
5 struct _AccountWatcher {
6 AgManager *manager;
7 /* A hash table of the enabled accounts we know of.
8- * Keys are account ID integers, and AccountInfo structs as values.
9+ * Keys are "<accountId>/<serviceName>", and AccountInfo structs as values.
10 */
11 GHashTable *services;
12
13- gulong enabled_event_signal_id;
14- gulong account_deleted_signal_id;
15-
16 AccountEnabledCallback callback;
17 void *user_data;
18 };
19@@ -51,9 +48,7 @@
20 GVariant *auth_params;
21 GVariant *session_data;
22
23- gulong enabled_signal_id;
24 AgAccountId account_id;
25- gboolean enabled; /* the last known state of the account */
26 };
27
28 static void account_info_clear_login(AccountInfo *info) {
29@@ -74,11 +69,6 @@
30
31 static void account_info_free(AccountInfo *info) {
32 account_info_clear_login(info);
33- if (info->enabled_signal_id != 0) {
34- g_signal_handler_disconnect(
35- info->account_service, info->enabled_signal_id);
36- }
37- info->enabled_signal_id = 0;
38 if (info->account_service) {
39 g_object_unref(info->account_service);
40 info->account_service = NULL;
41@@ -116,7 +106,7 @@
42 service_type,
43 service_name,
44 error,
45- info->enabled,
46+ TRUE,
47 client_id,
48 client_secret,
49 access_token,
50@@ -178,24 +168,6 @@
51 ag_auth_data_unref(auth_data);
52 }
53
54-static void account_info_enabled_cb(
55- AgAccountService *account_service, gboolean enabled, AccountInfo *info) {
56- trace("account_info_enabled_cb for %u, enabled=%d\n", info->account_id, enabled);
57- if (info->enabled == enabled) {
58- /* no change */
59- return;
60- }
61- info->enabled = enabled;
62-
63- if (enabled) {
64- account_info_login(info);
65- } else {
66- account_info_clear_login(info);
67- // Send notification that account has been disabled */
68- account_info_notify(info, NULL);
69- }
70-}
71-
72 static AccountInfo *account_info_new(AccountWatcher *watcher, AgAccountService *account_service) {
73 AccountInfo *info = g_new0(AccountInfo, 1);
74 info->watcher = watcher;
75@@ -204,99 +176,85 @@
76 AgAccount *account = ag_account_service_get_account(account_service);
77 g_object_get(account, "id", &info->account_id, NULL);
78
79- info->enabled_signal_id = g_signal_connect(
80- account_service, "enabled",
81- G_CALLBACK(account_info_enabled_cb), info);
82- // Set initial state
83- account_info_enabled_cb(account_service, ag_account_service_get_enabled(account_service), info);
84-
85 return info;
86 }
87
88-static void account_watcher_enabled_event_cb(
89- AgManager *manager, AgAccountId account_id, AccountWatcher *watcher) {
90- trace("enabled-event for %u\n", account_id);
91- if (g_hash_table_contains(watcher->services, GUINT_TO_POINTER(account_id))) {
92- /* We are already tracking this account */
93- return;
94- }
95- AgAccount *account = ag_manager_get_account(manager, account_id);
96- if (account == NULL) {
97- /* There was a problem looking up the account */
98- return;
99- }
100- /* Since our AgManager is restricted to a particular service type,
101- * pick the first service for the account. */
102- GList *services = ag_account_list_services(account);
103- if (services != NULL) {
104- AgService *service = services->data;
105- AgAccountService *account_service = ag_account_service_new(
106- account, service);
107- AccountInfo *info = account_info_new(watcher, account_service);
108- g_object_unref(account_service);
109- g_hash_table_insert(watcher->services, GUINT_TO_POINTER(account_id), info);
110- }
111- ag_service_list_free(services);
112- g_object_unref(account);
113-}
114-
115-static void account_watcher_account_deleted_cb(
116- AgManager *manager, AgAccountId account_id, AccountWatcher *watcher) {
117- trace("account-deleted for %u\n", account_id);
118- /* A disabled event should have been sent prior to this, so no
119- * need to send any notification. */
120- g_hash_table_remove(watcher->services, GUINT_TO_POINTER(account_id));
121-}
122-
123 static gboolean account_watcher_setup(void *user_data) {
124 AccountWatcher *watcher = (AccountWatcher *)user_data;
125
126- /* Track changes to accounts */
127- watcher->enabled_event_signal_id = g_signal_connect(
128- watcher->manager, "enabled-event",
129- G_CALLBACK(account_watcher_enabled_event_cb), watcher);
130- watcher->account_deleted_signal_id = g_signal_connect(
131- watcher->manager, "account-deleted",
132- G_CALLBACK(account_watcher_account_deleted_cb), watcher);
133-
134 /* Now check initial state */
135- GList *enabled_accounts = ag_manager_list(watcher->manager);
136+ GList *enabled_accounts =
137+ ag_manager_get_enabled_account_services(watcher->manager);
138+ GList *old_services = g_hash_table_get_keys(watcher->services);
139+
140+ /* Update the services table */
141 GList *l;
142 for (l = enabled_accounts; l != NULL; l = l->next) {
143- AgAccountId account_id = GPOINTER_TO_UINT(l->data);
144- account_watcher_enabled_event_cb(watcher->manager, account_id, watcher);
145- }
146- ag_manager_list_free(enabled_accounts);
147+ AgAccountService *account_service = l->data;
148+ AgAccountId id = ag_account_service_get_account(account_service)->id;
149+ AgService *service = ag_account_service_get_service(account_service);
150+ char *key = g_strdup_printf("%d/%s", id, ag_service_get_name(service));
151+
152+ AccountInfo *info = g_hash_table_lookup(watcher->services, key);
153+ if (info) {
154+ GList *node = g_list_find_custom(old_services, key,
155+ (GCompareFunc)g_strcmp0);
156+ old_services = g_list_remove_link(old_services, node);
157+ g_free(key);
158+ } else {
159+ trace("adding account %s\n", key);
160+ info = account_info_new(watcher, account_service);
161+ g_hash_table_insert(watcher->services, key, info);
162+ }
163+ account_info_login(info);
164+ }
165+ g_list_free_full(enabled_accounts, g_object_unref);
166+
167+ /* Remove from the table the accounts which are no longer enabled */
168+ for (l = old_services; l != NULL; l = l->next) {
169+ char *key = l->data;
170+ trace("removing account %s\n", key);
171+ g_hash_table_remove(watcher->services, key);
172+ }
173+ g_list_free(old_services);
174
175 return G_SOURCE_REMOVE;
176 }
177
178-AccountWatcher *account_watcher_new(const char *service_type,
179- AccountEnabledCallback callback,
180+AccountWatcher *account_watcher_new(AccountEnabledCallback callback,
181 void *user_data) {
182 AccountWatcher *watcher = g_new0(AccountWatcher, 1);
183
184- watcher->manager = ag_manager_new_for_service_type(service_type);
185+ watcher->manager = ag_manager_new();
186 watcher->services = g_hash_table_new_full(
187- g_direct_hash, g_direct_equal, NULL, (GDestroyNotify)account_info_free);
188+ g_str_hash, g_str_equal, g_free, (GDestroyNotify)account_info_free);
189 watcher->callback = callback;
190 watcher->user_data = user_data;
191
192+ return watcher;
193+}
194+
195+void account_watcher_run(AccountWatcher *watcher) {
196 /* Make sure main setup occurs within the mainloop thread */
197 g_idle_add(account_watcher_setup, watcher);
198- return watcher;
199 }
200
201 struct refresh_info {
202 AccountWatcher *watcher;
203 AgAccountId account_id;
204+ char *service_name;
205 };
206
207+static void refresh_info_free(struct refresh_info *data) {
208+ g_free(data->service_name);
209+ g_free(data);
210+}
211+
212 static gboolean account_watcher_refresh_cb(void *user_data) {
213 struct refresh_info *data = (struct refresh_info *)user_data;
214
215- AccountInfo *info = g_hash_table_lookup(
216- data->watcher->services, GUINT_TO_POINTER(data->account_id));
217+ char *key = g_strdup_printf("%d/%s", data->account_id, data->service_name);
218+ AccountInfo *info = g_hash_table_lookup(data->watcher->services, key);
219 if (info != NULL) {
220 account_info_login(info);
221 }
222@@ -304,10 +262,12 @@
223 return G_SOURCE_REMOVE;
224 }
225
226-void account_watcher_refresh(AccountWatcher *watcher, unsigned int account_id) {
227+void account_watcher_refresh(AccountWatcher *watcher, unsigned int account_id,
228+ const char *service_name) {
229 struct refresh_info *data = g_new(struct refresh_info, 1);
230 data->watcher = watcher;
231 data->account_id = account_id;
232+ data->service_name = g_strdup(service_name);
233 g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, account_watcher_refresh_cb,
234- data, g_free);
235+ data, (GDestroyNotify)refresh_info_free);
236 }
237
238=== modified file 'accounts/account-watcher.h'
239--- accounts/account-watcher.h 2016-04-19 19:58:25 +0000
240+++ accounts/account-watcher.h 2016-07-22 08:01:34 +0000
241@@ -32,10 +32,12 @@
242 const char *token_secret,
243 void *user_data);
244
245-AccountWatcher *account_watcher_new(const char *service_type,
246- AccountEnabledCallback callback,
247+AccountWatcher *account_watcher_new(AccountEnabledCallback callback,
248 void *user_data);
249+void account_watcher_run(AccountWatcher *watcher);
250
251-void account_watcher_refresh(AccountWatcher *watcher, unsigned int account_id);
252+void account_watcher_refresh(AccountWatcher *watcher,
253+ unsigned int account_id,
254+ const char *service_name);
255
256 #endif
257
258=== modified file 'accounts/accounts.c'
259--- accounts/accounts.c 2016-04-19 19:58:25 +0000
260+++ accounts/accounts.c 2016-07-22 08:01:34 +0000
261@@ -1,6 +1,6 @@
262 #include "_cgo_export.h"
263
264-AccountWatcher *watch_for_service_type(const char *service_type) {
265+AccountWatcher *watch() {
266 /* Transfer service names to hash table */
267 if (FALSE) {
268 /* The Go callback doesn't quite match the
269@@ -20,6 +20,6 @@
270 }
271
272 AccountWatcher *watcher = account_watcher_new(
273- service_type, (AccountEnabledCallback)authCallback, NULL);
274+ (AccountEnabledCallback)authCallback, NULL);
275 return watcher;
276 }
277
278=== modified file 'accounts/accounts.go'
279--- accounts/accounts.go 2016-04-19 19:58:25 +0000
280+++ accounts/accounts.go 2016-07-22 08:01:34 +0000
281@@ -22,7 +22,7 @@
282 #include <glib.h>
283 #include "account-watcher.h"
284
285-AccountWatcher *watch_for_service_type(const char *service_type);
286+AccountWatcher *watch();
287 */
288 import "C"
289 import (
290@@ -54,12 +54,10 @@
291 authChannelsLock sync.Mutex
292 )
293
294-// NewWatcher creates a new account watcher for the given service names
295-func NewWatcher(serviceType string) *Watcher {
296+// NewWatcher creates a new account watcher
297+func NewWatcher() *Watcher {
298 w := new(Watcher)
299- cServiceType := C.CString(serviceType)
300- defer C.free(unsafe.Pointer(cServiceType))
301- w.watcher = C.watch_for_service_type(cServiceType)
302+ w.watcher = C.watch()
303
304 ch := make(chan AuthData)
305 w.C = ch
306@@ -70,10 +68,16 @@
307 return w
308 }
309
310+// Walk through the enabled accounts, and get auth tokens for each of them.
311+// The new access token will be delivered over the watcher's channel.
312+func (w *Watcher) Run() {
313+ C.account_watcher_run(w.watcher)
314+}
315+
316 // Refresh requests that the token for the given account be refreshed.
317 // The new access token will be delivered over the watcher's channel.
318-func (w *Watcher) Refresh(accountId uint) {
319- C.account_watcher_refresh(w.watcher, C.uint(accountId))
320+func (w *Watcher) Refresh(accountId uint, serviceName string) {
321+ C.account_watcher_refresh(w.watcher, C.uint(accountId), C.CString(serviceName))
322 }
323
324 //export authCallback
325
326=== renamed file 'cmd/account-polld/account_manager.go' => 'cmd/account-polld/account_service.go'
327--- cmd/account-polld/account_manager.go 2016-06-30 19:21:46 +0000
328+++ cmd/account-polld/account_service.go 2016-07-22 08:01:34 +0000
329@@ -26,7 +26,7 @@
330 "launchpad.net/ubuntu-push/click"
331 )
332
333-type AccountManager struct {
334+type AccountService struct {
335 watcher *accounts.Watcher
336 authData accounts.AuthData
337 plugin plugins.Plugin
338@@ -51,8 +51,8 @@
339 clickNotInstalledError = errors.New("Click not installed")
340 )
341
342-func NewAccountManager(watcher *accounts.Watcher, postWatch chan *PostWatch, plugin plugins.Plugin) *AccountManager {
343- return &AccountManager{
344+func NewAccountService(watcher *accounts.Watcher, postWatch chan *PostWatch, plugin plugins.Plugin) *AccountService {
345+ return &AccountService{
346 watcher: watcher,
347 plugin: plugin,
348 postWatch: postWatch,
349@@ -61,20 +61,18 @@
350 }
351 }
352
353-func (a *AccountManager) Delete() {
354+func (a *AccountService) Delete() {
355 close(a.authChan)
356 close(a.doneChan)
357 }
358
359 // Poll() always needs to be called asynchronously as otherwise qtcontacs' GetAvatar()
360 // will raise an error: "QSocketNotifier: Can only be used with threads started with QThread"
361-func (a *AccountManager) Poll(bootstrap bool) {
362+func (a *AccountService) Poll(bootstrap bool) {
363 gotNewAuthData := false
364- if !a.authData.Enabled {
365- if a.authData, gotNewAuthData = <-a.authChan; !gotNewAuthData {
366- log.Println("Account", a.authData.AccountId, "no longer enabled")
367- return
368- }
369+ if a.authData, gotNewAuthData = <-a.authChan; !gotNewAuthData {
370+ log.Println("Account", a.authData.AccountId, "no longer enabled")
371+ return
372 }
373
374 if a.penaltyCount > 0 {
375@@ -126,7 +124,7 @@
376 // and mark the data as disabled.
377 // Do not refresh immediately when we just got new (faulty) auth data as immediately trying
378 // again is probably not going to help. Instead, we wait for the next poll cycle.
379- a.watcher.Refresh(a.authData.AccountId)
380+ a.watcher.Refresh(a.authData.AccountId, a.authData.ServiceName)
381 a.authData.Enabled = false
382 a.authData.Error = err
383 }
384@@ -139,7 +137,7 @@
385 log.Printf("Ending poll for account %d", a.authData.AccountId)
386 }
387
388-func (a *AccountManager) poll() {
389+func (a *AccountService) poll() {
390 log.Println("Polling account", a.authData.AccountId)
391 if !isClickInstalled(a.plugin.ApplicationId()) {
392 log.Println(
393@@ -167,7 +165,7 @@
394 }
395 }
396
397-func (a *AccountManager) updateAuthData(authData accounts.AuthData) {
398+func (a *AccountService) updateAuthData(authData accounts.AuthData) {
399 a.authChan <- authData
400 }
401
402
403=== modified file 'cmd/account-polld/main.go'
404--- cmd/account-polld/main.go 2016-04-21 23:33:48 +0000
405+++ cmd/account-polld/main.go 2016-07-22 08:01:34 +0000
406@@ -41,16 +41,13 @@
407 }
408
409 type AccountKey struct {
410- serviceType string
411+ serviceId string
412 accountId uint
413 }
414
415 /* Use identifiers and API keys provided by the respective webapps which are the official
416 end points for the notifications */
417 const (
418- SERVICETYPE_WEBAPPS = "webapps"
419- SERVICETYPE_CALENDAR = "calendar"
420-
421 SERVICENAME_GMAIL = "com.ubuntu.developer.webapps.webapp-gmail_webapp-gmail"
422 SERVICENAME_TWITTER = "com.ubuntu.developer.webapps.webapp-twitter_webapp-twitter"
423 SERVICENAME_GCALENDAR = "google-caldav"
424@@ -101,16 +98,14 @@
425 }
426
427 func monitorAccounts(postWatch chan *PostWatch, pollBus *pollbus.PollBus) {
428- watchers := make(map[string]*accounts.Watcher)
429- watchers[SERVICETYPE_WEBAPPS] = accounts.NewWatcher(SERVICETYPE_WEBAPPS)
430- watchers[SERVICETYPE_CALENDAR] = accounts.NewWatcher(SERVICETYPE_CALENDAR)
431+ watcher := accounts.NewWatcher()
432
433- mgr := make(map[AccountKey]*AccountManager)
434+ mgr := make(map[AccountKey]*AccountService)
435
436 var wg sync.WaitGroup
437
438 pullAccount := func(data accounts.AuthData) bool {
439- accountKey := AccountKey{data.ServiceType, data.AccountId}
440+ accountKey := AccountKey{data.ServiceName, data.AccountId}
441 if account, ok := mgr[accountKey]; ok {
442 if data.Enabled {
443 log.Println("New account data for existing account with id", data.AccountId)
444@@ -131,7 +126,7 @@
445 }
446 } else if data.Enabled {
447 var plugin plugins.Plugin
448- log.Println("Creat plugin for service: ", data.ServiceName)
449+ log.Println("Creating plugin for service: ", data.ServiceName)
450 switch data.ServiceName {
451 case SERVICENAME_GMAIL:
452 log.Println("Creating account with id", data.AccountId, "for", data.ServiceName)
453@@ -147,7 +142,7 @@
454 log.Println("Unhandled account with id", data.AccountId, "for", data.ServiceName)
455 return false
456 }
457- mgr[accountKey] = NewAccountManager(watchers[data.ServiceType], postWatch, plugin)
458+ mgr[accountKey] = NewAccountService(watcher, postWatch, plugin)
459 mgr[accountKey].updateAuthData(data)
460 wg.Add(1)
461 go func() {
462@@ -165,27 +160,14 @@
463 L:
464 for {
465 select {
466- case data := <-watchers[SERVICETYPE_CALENDAR].C:
467- if pullAccount(data) == false {
468- continue L
469- }
470- case data := <-watchers[SERVICETYPE_WEBAPPS].C:
471- if pullAccount(data) == false {
472+ case data := <-watcher.C:
473+ if pullAccount(data) == false {
474+ log.Println("pullAccount returned false, continuing")
475 continue L
476 }
477 case <-pollBus.PollChan:
478 wg.Wait() // Finish all running Poll() calls before potentially polling the same accounts again
479- for _, v := range mgr {
480- if v.authData.Error != plugins.ErrTokenExpired { // Do not poll if the new token hasn't been loaded yet
481- wg.Add(1)
482- go func(accountManager *AccountManager) {
483- defer wg.Done()
484- accountManager.Poll(false)
485- }(v)
486- } else {
487- log.Println("Skipping account with id", v.authData.AccountId, "as it is refreshing its token")
488- }
489- }
490+ watcher.Run()
491 wg.Wait()
492 pollBus.SignalDone()
493 }
494
495=== modified file 'cmd/account-watcher-test/main.go'
496--- cmd/account-watcher-test/main.go 2014-07-24 05:38:51 +0000
497+++ cmd/account-watcher-test/main.go 2016-07-22 08:01:34 +0000
498@@ -2,14 +2,12 @@
499
500 import (
501 "fmt"
502- "os"
503
504 "launchpad.net/account-polld/accounts"
505 )
506
507 func main() {
508- // Expects a list of service names as command line arguments
509- for data := range accounts.NewWatcher(os.Args[1]).C {
510+ for data := range accounts.NewWatcher().C {
511 if data.Error != nil {
512 fmt.Println("Failed to authenticate account", data.AccountId, ":", data.Error)
513 } else {

Subscribers

People subscribed via source and target branches