# HG changeset patch # User Goffi # Date 1527851032 -7200 # Node ID eda7a1c6532a4411da5b5c8f95427e253e8224be # Parent 63ed5f6bd4eb12d91b36a6b55e63c012db74522d server: new getAffiliation method: getAffiliation allows to retrieve affiliation to a pubsub node for logged user. The method handle cache in user's session, avoiding requesting pubsub service when possible. diff -r 63ed5f6bd4eb -r eda7a1c6532a src/server/server.py --- a/src/server/server.py Fri Jun 01 12:58:20 2018 +0200 +++ b/src/server/server.py Fri Jun 01 13:03:52 2018 +0200 @@ -1920,6 +1920,37 @@ else: return (iface(session) for iface in args) + @defer.inlineCallbacks + def getAffiliation(self, request, service, node): + """retrieve pubsub node affiliation for current user + + use cache first, and request pubsub service if not cache is found + @param request(server.Request): request linked to the session + @param service(jid.JID): pubsub service + @param node(unicode): pubsub node + @return (unicode): affiliation + """ + sat_session = self.getSessionData(request, session_iface.ISATSession) + if sat_session.profile is None: + raise exceptions.InternalError(u'profile must be set to use this method') + affiliation = sat_session.getAffiliation(service, node) + if affiliation is not None: + defer.returnValue(affiliation) + else: + try: + affiliations = yield self.bridgeCall('psAffiliationsGet', service.full(), node, sat_session.profile) + except Exception as e: + log.warning("Can't retrieve affiliation for {service}/{node}: {reason}".format( + service=service, node=node, reason=e)) + affiliation = u"" + else: + try: + affiliation = affiliations[node] + except KeyError: + affiliation = u"" + sat_session.setAffiliation(service, node, affiliation) + defer.returnValue(affiliation) + ## Websocket (dynamic pages) ## def getWebsocketURL(self, request): diff -r 63ed5f6bd4eb -r eda7a1c6532a src/server/session_iface.py --- a/src/server/session_iface.py Fri Jun 01 12:58:20 2018 +0200 +++ b/src/server/session_iface.py Fri Jun 01 13:03:52 2018 +0200 @@ -19,11 +19,13 @@ from zope.interface import Interface, Attribute, implements from sat.tools.common import data_objects from libervia.server.constants import Const as C +from collections import OrderedDict import os.path import shortuuid import time FLAGS_KEY = '_flags' +MAX_CACHE_AFFILIATIONS = 100 # number of nodes to keep in cache class ISATSession(Interface): profile = Attribute("Sat profile") @@ -45,6 +47,7 @@ self.identities = data_objects.Identities() self.csrf_token = unicode(shortuuid.uuid()) self.pages_data = {} # used to keep data accross reloads (key is page instance) + self.affiliations = OrderedDict() # cache for node affiliations @property def cache_dir(self): @@ -125,6 +128,43 @@ else: return False + def getAffiliation(self, service, node): + """retrieve affiliation for a pubsub node + + @param service(jid.JID): pubsub service + @param node(unicode): pubsub node + @return (unicode, None): affiliation, or None if it is not in cache + """ + if service.resource: + raise ValueError(u"Service must not have a resource") + if not node: + raise ValueError(u"node must be set") + try: + affiliation = self.affiliations.pop((service, node)) + except KeyError: + return None + else: + # we replace at the top to get the most recently used on top + # so less recently used will be removed if cache is full + self.affiliations[(service, node)] = affiliation + return affiliation + + def setAffiliation(self, service, node, affiliation): + """cache affiliation for a node + + will empty cache when it become too big + @param service(jid.JID): pubsub service + @param node(unicode): pubsub node + @param affiliation(unicode): affiliation to this node + """ + if service.resource: + raise ValueError(u"Service must not have a resource") + if not node: + raise ValueError(u"node must be set") + self.affiliations[(service, node)] = affiliation + while len(self.affiliations) > MAX_CACHE_AFFILIATIONS: + self.affiliations.popitem(last=False) + class ISATGuestSession(Interface): id = Attribute("UUID of the guest")