changeset 2767:a97c43dc4924

core: findByFeatures speed improvments: - DeferredList are used instead of waiting for each disco individually - a Timeout of 10 s is set for jids, to avoid waiting for minutes when some entity is unreachable (which leads to terrible user experience while waiting for a discovery page)
author Goffi <goffi@goffi.org>
date Fri, 11 Jan 2019 19:44:46 +0100
parents 93a421de0e3d
children cb34af35af6f
files sat/core/sat_main.py
diffstat 1 files changed, 44 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/sat/core/sat_main.py	Fri Jan 11 16:35:13 2019 +0100
+++ b/sat/core/sat_main.py	Fri Jan 11 19:44:46 2019 +0100
@@ -872,11 +872,19 @@
         found_roster = {}
         if service:
             services_jids = yield self.findFeaturesSet(client, namespaces)
-            for service_jid in services_jids:
-                infos = yield self.getDiscoInfos(client, service_jid)
-                if identities is not None and not set(infos.identities.keys()).issuperset(
-                    identities
-                ):
+            services_infos  = yield defer.DeferredList(
+                [self.getDiscoInfos(client, service_jid) for service_jid in services_jids]
+            )
+
+            for idx, (success, infos) in enumerate(services_infos):
+                service_jid = services_jids[idx]
+                if not success:
+                    log.warning(
+                        _(u"Can't find features for service {service_jid}, ignoring")
+                        .format(service_jid=service_jid.full()))
+                    continue
+                if (identities is not None
+                    and not set(infos.identities.keys()).issuperset(identities)):
                     continue
                 found_identities = [
                     (cat, type_, name or u"")
@@ -890,6 +898,9 @@
         if roster:
             to_find.append((found_roster, client.roster.getJids()))
 
+        full_jids = []
+        d_list = []
+
         for found, jids in to_find:
             for jid_ in jids:
                 if jid_.resource:
@@ -913,17 +924,34 @@
                     full_jid = jid.JID(tuple=(jid_.user, jid_.host, resource))
                     if full_jid == client.jid and not local_device:
                         continue
-                    infos = yield self.getDiscoInfos(client, full_jid)
-                    if infos.features.issuperset(namespaces):
-                        if identities is not None and not set(
-                            infos.identities.keys()
-                        ).issuperset(identities):
-                            continue
-                        found_identities = [
-                            (cat, type_, name or u"")
-                            for (cat, type_), name in infos.identities.iteritems()
-                        ]
-                        found[full_jid.full()] = found_identities
+                    full_jids.append(full_jid)
+
+                    d_list.append(self.getDiscoInfos(client, full_jid))
+
+        d_list = defer.DeferredList(d_list)
+        # XXX: 10 seconds may be too low for slow connections (e.g. mobiles)
+        #      but for discovery, that's also the time the user will wait the first time
+        #      before seing the page.
+        d_list.addTimeout(10, reactor)
+        infos_data = yield d_list
+
+        for idx, (success, infos) in enumerate(infos_data):
+            full_jid = full_jids[idx]
+            if not success:
+                log.warning(
+                    _(u"Can't retrieve {full_jid} infos, ignoring")
+                    .format(full_jid=full_jid.full()))
+                continue
+            if infos.features.issuperset(namespaces):
+                if identities is not None and not set(
+                    infos.identities.keys()
+                ).issuperset(identities):
+                    continue
+                found_identities = [
+                    (cat, type_, name or u"")
+                    for (cat, type_), name in infos.identities.iteritems()
+                ]
+                found[full_jid.full()] = found_identities
 
         defer.returnValue((found_service, found_own, found_roster))