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)
This commit is contained in:
Goffi 2019-01-11 19:44:46 +01:00
commit c5a17cc9ef

View file

@ -872,11 +872,19 @@ class SAT(service.Service):
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 @@ class SAT(service.Service):
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 @@ class SAT(service.Service):
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))