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
=== modified file 'accounts/account-watcher.c'
--- accounts/account-watcher.c 2016-04-19 19:58:25 +0000
+++ accounts/account-watcher.c 2016-07-22 08:01:34 +0000
@@ -31,13 +31,10 @@
31struct _AccountWatcher {31struct _AccountWatcher {
32 AgManager *manager;32 AgManager *manager;
33 /* A hash table of the enabled accounts we know of.33 /* A hash table of the enabled accounts we know of.
34 * Keys are account ID integers, and AccountInfo structs as values.34 * Keys are "<accountId>/<serviceName>", and AccountInfo structs as values.
35 */35 */
36 GHashTable *services;36 GHashTable *services;
3737
38 gulong enabled_event_signal_id;
39 gulong account_deleted_signal_id;
40
41 AccountEnabledCallback callback;38 AccountEnabledCallback callback;
42 void *user_data;39 void *user_data;
43};40};
@@ -51,9 +48,7 @@
51 GVariant *auth_params;48 GVariant *auth_params;
52 GVariant *session_data;49 GVariant *session_data;
5350
54 gulong enabled_signal_id;
55 AgAccountId account_id;51 AgAccountId account_id;
56 gboolean enabled; /* the last known state of the account */
57};52};
5853
59static void account_info_clear_login(AccountInfo *info) {54static void account_info_clear_login(AccountInfo *info) {
@@ -74,11 +69,6 @@
7469
75static void account_info_free(AccountInfo *info) {70static void account_info_free(AccountInfo *info) {
76 account_info_clear_login(info);71 account_info_clear_login(info);
77 if (info->enabled_signal_id != 0) {
78 g_signal_handler_disconnect(
79 info->account_service, info->enabled_signal_id);
80 }
81 info->enabled_signal_id = 0;
82 if (info->account_service) {72 if (info->account_service) {
83 g_object_unref(info->account_service);73 g_object_unref(info->account_service);
84 info->account_service = NULL;74 info->account_service = NULL;
@@ -116,7 +106,7 @@
116 service_type,106 service_type,
117 service_name,107 service_name,
118 error,108 error,
119 info->enabled,109 TRUE,
120 client_id,110 client_id,
121 client_secret,111 client_secret,
122 access_token,112 access_token,
@@ -178,24 +168,6 @@
178 ag_auth_data_unref(auth_data);168 ag_auth_data_unref(auth_data);
179}169}
180170
181static void account_info_enabled_cb(
182 AgAccountService *account_service, gboolean enabled, AccountInfo *info) {
183 trace("account_info_enabled_cb for %u, enabled=%d\n", info->account_id, enabled);
184 if (info->enabled == enabled) {
185 /* no change */
186 return;
187 }
188 info->enabled = enabled;
189
190 if (enabled) {
191 account_info_login(info);
192 } else {
193 account_info_clear_login(info);
194 // Send notification that account has been disabled */
195 account_info_notify(info, NULL);
196 }
197}
198
199static AccountInfo *account_info_new(AccountWatcher *watcher, AgAccountService *account_service) {171static AccountInfo *account_info_new(AccountWatcher *watcher, AgAccountService *account_service) {
200 AccountInfo *info = g_new0(AccountInfo, 1);172 AccountInfo *info = g_new0(AccountInfo, 1);
201 info->watcher = watcher;173 info->watcher = watcher;
@@ -204,99 +176,85 @@
204 AgAccount *account = ag_account_service_get_account(account_service);176 AgAccount *account = ag_account_service_get_account(account_service);
205 g_object_get(account, "id", &info->account_id, NULL);177 g_object_get(account, "id", &info->account_id, NULL);
206178
207 info->enabled_signal_id = g_signal_connect(
208 account_service, "enabled",
209 G_CALLBACK(account_info_enabled_cb), info);
210 // Set initial state
211 account_info_enabled_cb(account_service, ag_account_service_get_enabled(account_service), info);
212
213 return info;179 return info;
214}180}
215181
216static void account_watcher_enabled_event_cb(
217 AgManager *manager, AgAccountId account_id, AccountWatcher *watcher) {
218 trace("enabled-event for %u\n", account_id);
219 if (g_hash_table_contains(watcher->services, GUINT_TO_POINTER(account_id))) {
220 /* We are already tracking this account */
221 return;
222 }
223 AgAccount *account = ag_manager_get_account(manager, account_id);
224 if (account == NULL) {
225 /* There was a problem looking up the account */
226 return;
227 }
228 /* Since our AgManager is restricted to a particular service type,
229 * pick the first service for the account. */
230 GList *services = ag_account_list_services(account);
231 if (services != NULL) {
232 AgService *service = services->data;
233 AgAccountService *account_service = ag_account_service_new(
234 account, service);
235 AccountInfo *info = account_info_new(watcher, account_service);
236 g_object_unref(account_service);
237 g_hash_table_insert(watcher->services, GUINT_TO_POINTER(account_id), info);
238 }
239 ag_service_list_free(services);
240 g_object_unref(account);
241}
242
243static void account_watcher_account_deleted_cb(
244 AgManager *manager, AgAccountId account_id, AccountWatcher *watcher) {
245 trace("account-deleted for %u\n", account_id);
246 /* A disabled event should have been sent prior to this, so no
247 * need to send any notification. */
248 g_hash_table_remove(watcher->services, GUINT_TO_POINTER(account_id));
249}
250
251static gboolean account_watcher_setup(void *user_data) {182static gboolean account_watcher_setup(void *user_data) {
252 AccountWatcher *watcher = (AccountWatcher *)user_data;183 AccountWatcher *watcher = (AccountWatcher *)user_data;
253184
254 /* Track changes to accounts */
255 watcher->enabled_event_signal_id = g_signal_connect(
256 watcher->manager, "enabled-event",
257 G_CALLBACK(account_watcher_enabled_event_cb), watcher);
258 watcher->account_deleted_signal_id = g_signal_connect(
259 watcher->manager, "account-deleted",
260 G_CALLBACK(account_watcher_account_deleted_cb), watcher);
261
262 /* Now check initial state */185 /* Now check initial state */
263 GList *enabled_accounts = ag_manager_list(watcher->manager);186 GList *enabled_accounts =
187 ag_manager_get_enabled_account_services(watcher->manager);
188 GList *old_services = g_hash_table_get_keys(watcher->services);
189
190 /* Update the services table */
264 GList *l;191 GList *l;
265 for (l = enabled_accounts; l != NULL; l = l->next) {192 for (l = enabled_accounts; l != NULL; l = l->next) {
266 AgAccountId account_id = GPOINTER_TO_UINT(l->data);193 AgAccountService *account_service = l->data;
267 account_watcher_enabled_event_cb(watcher->manager, account_id, watcher);194 AgAccountId id = ag_account_service_get_account(account_service)->id;
268 }195 AgService *service = ag_account_service_get_service(account_service);
269 ag_manager_list_free(enabled_accounts);196 char *key = g_strdup_printf("%d/%s", id, ag_service_get_name(service));
197
198 AccountInfo *info = g_hash_table_lookup(watcher->services, key);
199 if (info) {
200 GList *node = g_list_find_custom(old_services, key,
201 (GCompareFunc)g_strcmp0);
202 old_services = g_list_remove_link(old_services, node);
203 g_free(key);
204 } else {
205 trace("adding account %s\n", key);
206 info = account_info_new(watcher, account_service);
207 g_hash_table_insert(watcher->services, key, info);
208 }
209 account_info_login(info);
210 }
211 g_list_free_full(enabled_accounts, g_object_unref);
212
213 /* Remove from the table the accounts which are no longer enabled */
214 for (l = old_services; l != NULL; l = l->next) {
215 char *key = l->data;
216 trace("removing account %s\n", key);
217 g_hash_table_remove(watcher->services, key);
218 }
219 g_list_free(old_services);
270220
271 return G_SOURCE_REMOVE;221 return G_SOURCE_REMOVE;
272}222}
273223
274AccountWatcher *account_watcher_new(const char *service_type,224AccountWatcher *account_watcher_new(AccountEnabledCallback callback,
275 AccountEnabledCallback callback,
276 void *user_data) {225 void *user_data) {
277 AccountWatcher *watcher = g_new0(AccountWatcher, 1);226 AccountWatcher *watcher = g_new0(AccountWatcher, 1);
278227
279 watcher->manager = ag_manager_new_for_service_type(service_type);228 watcher->manager = ag_manager_new();
280 watcher->services = g_hash_table_new_full(229 watcher->services = g_hash_table_new_full(
281 g_direct_hash, g_direct_equal, NULL, (GDestroyNotify)account_info_free);230 g_str_hash, g_str_equal, g_free, (GDestroyNotify)account_info_free);
282 watcher->callback = callback;231 watcher->callback = callback;
283 watcher->user_data = user_data;232 watcher->user_data = user_data;
284233
234 return watcher;
235}
236
237void account_watcher_run(AccountWatcher *watcher) {
285 /* Make sure main setup occurs within the mainloop thread */238 /* Make sure main setup occurs within the mainloop thread */
286 g_idle_add(account_watcher_setup, watcher);239 g_idle_add(account_watcher_setup, watcher);
287 return watcher;
288}240}
289241
290struct refresh_info {242struct refresh_info {
291 AccountWatcher *watcher;243 AccountWatcher *watcher;
292 AgAccountId account_id;244 AgAccountId account_id;
245 char *service_name;
293};246};
294247
248static void refresh_info_free(struct refresh_info *data) {
249 g_free(data->service_name);
250 g_free(data);
251}
252
295static gboolean account_watcher_refresh_cb(void *user_data) {253static gboolean account_watcher_refresh_cb(void *user_data) {
296 struct refresh_info *data = (struct refresh_info *)user_data;254 struct refresh_info *data = (struct refresh_info *)user_data;
297255
298 AccountInfo *info = g_hash_table_lookup(256 char *key = g_strdup_printf("%d/%s", data->account_id, data->service_name);
299 data->watcher->services, GUINT_TO_POINTER(data->account_id));257 AccountInfo *info = g_hash_table_lookup(data->watcher->services, key);
300 if (info != NULL) {258 if (info != NULL) {
301 account_info_login(info);259 account_info_login(info);
302 }260 }
@@ -304,10 +262,12 @@
304 return G_SOURCE_REMOVE;262 return G_SOURCE_REMOVE;
305}263}
306264
307void account_watcher_refresh(AccountWatcher *watcher, unsigned int account_id) {265void account_watcher_refresh(AccountWatcher *watcher, unsigned int account_id,
266 const char *service_name) {
308 struct refresh_info *data = g_new(struct refresh_info, 1);267 struct refresh_info *data = g_new(struct refresh_info, 1);
309 data->watcher = watcher;268 data->watcher = watcher;
310 data->account_id = account_id;269 data->account_id = account_id;
270 data->service_name = g_strdup(service_name);
311 g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, account_watcher_refresh_cb,271 g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, account_watcher_refresh_cb,
312 data, g_free);272 data, (GDestroyNotify)refresh_info_free);
313}273}
314274
=== modified file 'accounts/account-watcher.h'
--- accounts/account-watcher.h 2016-04-19 19:58:25 +0000
+++ accounts/account-watcher.h 2016-07-22 08:01:34 +0000
@@ -32,10 +32,12 @@
32 const char *token_secret,32 const char *token_secret,
33 void *user_data);33 void *user_data);
3434
35AccountWatcher *account_watcher_new(const char *service_type,35AccountWatcher *account_watcher_new(AccountEnabledCallback callback,
36 AccountEnabledCallback callback,
37 void *user_data);36 void *user_data);
37void account_watcher_run(AccountWatcher *watcher);
3838
39void account_watcher_refresh(AccountWatcher *watcher, unsigned int account_id);39void account_watcher_refresh(AccountWatcher *watcher,
40 unsigned int account_id,
41 const char *service_name);
4042
41#endif43#endif
4244
=== modified file 'accounts/accounts.c'
--- accounts/accounts.c 2016-04-19 19:58:25 +0000
+++ accounts/accounts.c 2016-07-22 08:01:34 +0000
@@ -1,6 +1,6 @@
1#include "_cgo_export.h"1#include "_cgo_export.h"
22
3AccountWatcher *watch_for_service_type(const char *service_type) {3AccountWatcher *watch() {
4 /* Transfer service names to hash table */4 /* Transfer service names to hash table */
5 if (FALSE) {5 if (FALSE) {
6 /* The Go callback doesn't quite match the6 /* The Go callback doesn't quite match the
@@ -20,6 +20,6 @@
20 }20 }
2121
22 AccountWatcher *watcher = account_watcher_new(22 AccountWatcher *watcher = account_watcher_new(
23 service_type, (AccountEnabledCallback)authCallback, NULL);23 (AccountEnabledCallback)authCallback, NULL);
24 return watcher;24 return watcher;
25}25}
2626
=== modified file 'accounts/accounts.go'
--- accounts/accounts.go 2016-04-19 19:58:25 +0000
+++ accounts/accounts.go 2016-07-22 08:01:34 +0000
@@ -22,7 +22,7 @@
22#include <glib.h>22#include <glib.h>
23#include "account-watcher.h"23#include "account-watcher.h"
2424
25AccountWatcher *watch_for_service_type(const char *service_type);25AccountWatcher *watch();
26*/26*/
27import "C"27import "C"
28import (28import (
@@ -54,12 +54,10 @@
54 authChannelsLock sync.Mutex54 authChannelsLock sync.Mutex
55)55)
5656
57// NewWatcher creates a new account watcher for the given service names57// NewWatcher creates a new account watcher
58func NewWatcher(serviceType string) *Watcher {58func NewWatcher() *Watcher {
59 w := new(Watcher)59 w := new(Watcher)
60 cServiceType := C.CString(serviceType)60 w.watcher = C.watch()
61 defer C.free(unsafe.Pointer(cServiceType))
62 w.watcher = C.watch_for_service_type(cServiceType)
6361
64 ch := make(chan AuthData)62 ch := make(chan AuthData)
65 w.C = ch63 w.C = ch
@@ -70,10 +68,16 @@
70 return w68 return w
71}69}
7270
71// Walk through the enabled accounts, and get auth tokens for each of them.
72// The new access token will be delivered over the watcher's channel.
73func (w *Watcher) Run() {
74 C.account_watcher_run(w.watcher)
75}
76
73// Refresh requests that the token for the given account be refreshed.77// Refresh requests that the token for the given account be refreshed.
74// The new access token will be delivered over the watcher's channel.78// The new access token will be delivered over the watcher's channel.
75func (w *Watcher) Refresh(accountId uint) {79func (w *Watcher) Refresh(accountId uint, serviceName string) {
76 C.account_watcher_refresh(w.watcher, C.uint(accountId))80 C.account_watcher_refresh(w.watcher, C.uint(accountId), C.CString(serviceName))
77}81}
7882
79//export authCallback83//export authCallback
8084
=== renamed file 'cmd/account-polld/account_manager.go' => 'cmd/account-polld/account_service.go'
--- cmd/account-polld/account_manager.go 2016-06-30 19:21:46 +0000
+++ cmd/account-polld/account_service.go 2016-07-22 08:01:34 +0000
@@ -26,7 +26,7 @@
26 "launchpad.net/ubuntu-push/click"26 "launchpad.net/ubuntu-push/click"
27)27)
2828
29type AccountManager struct {29type AccountService struct {
30 watcher *accounts.Watcher30 watcher *accounts.Watcher
31 authData accounts.AuthData31 authData accounts.AuthData
32 plugin plugins.Plugin32 plugin plugins.Plugin
@@ -51,8 +51,8 @@
51 clickNotInstalledError = errors.New("Click not installed")51 clickNotInstalledError = errors.New("Click not installed")
52)52)
5353
54func NewAccountManager(watcher *accounts.Watcher, postWatch chan *PostWatch, plugin plugins.Plugin) *AccountManager {54func NewAccountService(watcher *accounts.Watcher, postWatch chan *PostWatch, plugin plugins.Plugin) *AccountService {
55 return &AccountManager{55 return &AccountService{
56 watcher: watcher,56 watcher: watcher,
57 plugin: plugin,57 plugin: plugin,
58 postWatch: postWatch,58 postWatch: postWatch,
@@ -61,20 +61,18 @@
61 }61 }
62}62}
6363
64func (a *AccountManager) Delete() {64func (a *AccountService) Delete() {
65 close(a.authChan)65 close(a.authChan)
66 close(a.doneChan)66 close(a.doneChan)
67}67}
6868
69// Poll() always needs to be called asynchronously as otherwise qtcontacs' GetAvatar()69// Poll() always needs to be called asynchronously as otherwise qtcontacs' GetAvatar()
70// will raise an error: "QSocketNotifier: Can only be used with threads started with QThread"70// will raise an error: "QSocketNotifier: Can only be used with threads started with QThread"
71func (a *AccountManager) Poll(bootstrap bool) {71func (a *AccountService) Poll(bootstrap bool) {
72 gotNewAuthData := false72 gotNewAuthData := false
73 if !a.authData.Enabled {73 if a.authData, gotNewAuthData = <-a.authChan; !gotNewAuthData {
74 if a.authData, gotNewAuthData = <-a.authChan; !gotNewAuthData {74 log.Println("Account", a.authData.AccountId, "no longer enabled")
75 log.Println("Account", a.authData.AccountId, "no longer enabled")75 return
76 return
77 }
78 }76 }
7977
80 if a.penaltyCount > 0 {78 if a.penaltyCount > 0 {
@@ -126,7 +124,7 @@
126 // and mark the data as disabled.124 // and mark the data as disabled.
127 // Do not refresh immediately when we just got new (faulty) auth data as immediately trying125 // Do not refresh immediately when we just got new (faulty) auth data as immediately trying
128 // again is probably not going to help. Instead, we wait for the next poll cycle.126 // again is probably not going to help. Instead, we wait for the next poll cycle.
129 a.watcher.Refresh(a.authData.AccountId)127 a.watcher.Refresh(a.authData.AccountId, a.authData.ServiceName)
130 a.authData.Enabled = false128 a.authData.Enabled = false
131 a.authData.Error = err129 a.authData.Error = err
132 }130 }
@@ -139,7 +137,7 @@
139 log.Printf("Ending poll for account %d", a.authData.AccountId)137 log.Printf("Ending poll for account %d", a.authData.AccountId)
140}138}
141139
142func (a *AccountManager) poll() {140func (a *AccountService) poll() {
143 log.Println("Polling account", a.authData.AccountId)141 log.Println("Polling account", a.authData.AccountId)
144 if !isClickInstalled(a.plugin.ApplicationId()) {142 if !isClickInstalled(a.plugin.ApplicationId()) {
145 log.Println(143 log.Println(
@@ -167,7 +165,7 @@
167 }165 }
168}166}
169167
170func (a *AccountManager) updateAuthData(authData accounts.AuthData) {168func (a *AccountService) updateAuthData(authData accounts.AuthData) {
171 a.authChan <- authData169 a.authChan <- authData
172}170}
173171
174172
=== modified file 'cmd/account-polld/main.go'
--- cmd/account-polld/main.go 2016-04-21 23:33:48 +0000
+++ cmd/account-polld/main.go 2016-07-22 08:01:34 +0000
@@ -41,16 +41,13 @@
41}41}
4242
43type AccountKey struct {43type AccountKey struct {
44 serviceType string44 serviceId string
45 accountId uint45 accountId uint
46}46}
4747
48/* Use identifiers and API keys provided by the respective webapps which are the official48/* Use identifiers and API keys provided by the respective webapps which are the official
49 end points for the notifications */49 end points for the notifications */
50const (50const (
51 SERVICETYPE_WEBAPPS = "webapps"
52 SERVICETYPE_CALENDAR = "calendar"
53
54 SERVICENAME_GMAIL = "com.ubuntu.developer.webapps.webapp-gmail_webapp-gmail"51 SERVICENAME_GMAIL = "com.ubuntu.developer.webapps.webapp-gmail_webapp-gmail"
55 SERVICENAME_TWITTER = "com.ubuntu.developer.webapps.webapp-twitter_webapp-twitter"52 SERVICENAME_TWITTER = "com.ubuntu.developer.webapps.webapp-twitter_webapp-twitter"
56 SERVICENAME_GCALENDAR = "google-caldav"53 SERVICENAME_GCALENDAR = "google-caldav"
@@ -101,16 +98,14 @@
101}98}
10299
103func monitorAccounts(postWatch chan *PostWatch, pollBus *pollbus.PollBus) {100func monitorAccounts(postWatch chan *PostWatch, pollBus *pollbus.PollBus) {
104 watchers := make(map[string]*accounts.Watcher)101 watcher := accounts.NewWatcher()
105 watchers[SERVICETYPE_WEBAPPS] = accounts.NewWatcher(SERVICETYPE_WEBAPPS)
106 watchers[SERVICETYPE_CALENDAR] = accounts.NewWatcher(SERVICETYPE_CALENDAR)
107102
108 mgr := make(map[AccountKey]*AccountManager)103 mgr := make(map[AccountKey]*AccountService)
109104
110 var wg sync.WaitGroup105 var wg sync.WaitGroup
111106
112 pullAccount := func(data accounts.AuthData) bool {107 pullAccount := func(data accounts.AuthData) bool {
113 accountKey := AccountKey{data.ServiceType, data.AccountId}108 accountKey := AccountKey{data.ServiceName, data.AccountId}
114 if account, ok := mgr[accountKey]; ok {109 if account, ok := mgr[accountKey]; ok {
115 if data.Enabled {110 if data.Enabled {
116 log.Println("New account data for existing account with id", data.AccountId)111 log.Println("New account data for existing account with id", data.AccountId)
@@ -131,7 +126,7 @@
131 }126 }
132 } else if data.Enabled {127 } else if data.Enabled {
133 var plugin plugins.Plugin128 var plugin plugins.Plugin
134 log.Println("Creat plugin for service: ", data.ServiceName)129 log.Println("Creating plugin for service: ", data.ServiceName)
135 switch data.ServiceName {130 switch data.ServiceName {
136 case SERVICENAME_GMAIL:131 case SERVICENAME_GMAIL:
137 log.Println("Creating account with id", data.AccountId, "for", data.ServiceName)132 log.Println("Creating account with id", data.AccountId, "for", data.ServiceName)
@@ -147,7 +142,7 @@
147 log.Println("Unhandled account with id", data.AccountId, "for", data.ServiceName)142 log.Println("Unhandled account with id", data.AccountId, "for", data.ServiceName)
148 return false143 return false
149 }144 }
150 mgr[accountKey] = NewAccountManager(watchers[data.ServiceType], postWatch, plugin)145 mgr[accountKey] = NewAccountService(watcher, postWatch, plugin)
151 mgr[accountKey].updateAuthData(data)146 mgr[accountKey].updateAuthData(data)
152 wg.Add(1)147 wg.Add(1)
153 go func() {148 go func() {
@@ -165,27 +160,14 @@
165L:160L:
166 for {161 for {
167 select {162 select {
168 case data := <-watchers[SERVICETYPE_CALENDAR].C:163 case data := <-watcher.C:
169 if pullAccount(data) == false {164 if pullAccount(data) == false {
170 continue L165 log.Println("pullAccount returned false, continuing")
171 }
172 case data := <-watchers[SERVICETYPE_WEBAPPS].C:
173 if pullAccount(data) == false {
174 continue L166 continue L
175 }167 }
176 case <-pollBus.PollChan:168 case <-pollBus.PollChan:
177 wg.Wait() // Finish all running Poll() calls before potentially polling the same accounts again169 wg.Wait() // Finish all running Poll() calls before potentially polling the same accounts again
178 for _, v := range mgr {170 watcher.Run()
179 if v.authData.Error != plugins.ErrTokenExpired { // Do not poll if the new token hasn't been loaded yet
180 wg.Add(1)
181 go func(accountManager *AccountManager) {
182 defer wg.Done()
183 accountManager.Poll(false)
184 }(v)
185 } else {
186 log.Println("Skipping account with id", v.authData.AccountId, "as it is refreshing its token")
187 }
188 }
189 wg.Wait()171 wg.Wait()
190 pollBus.SignalDone()172 pollBus.SignalDone()
191 }173 }
192174
=== modified file 'cmd/account-watcher-test/main.go'
--- cmd/account-watcher-test/main.go 2014-07-24 05:38:51 +0000
+++ cmd/account-watcher-test/main.go 2016-07-22 08:01:34 +0000
@@ -2,14 +2,12 @@
22
3import (3import (
4 "fmt"4 "fmt"
5 "os"
65
7 "launchpad.net/account-polld/accounts"6 "launchpad.net/account-polld/accounts"
8)7)
98
10func main() {9func main() {
11 // Expects a list of service names as command line arguments10 for data := range accounts.NewWatcher().C {
12 for data := range accounts.NewWatcher(os.Args[1]).C {
13 if data.Error != nil {11 if data.Error != nil {
14 fmt.Println("Failed to authenticate account", data.AccountId, ":", data.Error)12 fmt.Println("Failed to authenticate account", data.AccountId, ":", data.Error)
15 } else {13 } else {

Subscribers

People subscribed via source and target branches