Mercurial > libervia-pubsub
diff sat_pubsub/backend.py @ 318:d13526c0eb32
RSM improvments/refactoring:
- a warning message is displayed if maxItems == 0 in getItems, and an empty list is returned in this case
- use the new container.ItemData instead of doing tuple (un)packing
- the list of ItemData => list of domish.Element conversion is done at the end of the workflow
- rsm request is checked in self._items_rsm directly
- better handling of Response.index in _items_rsm
- itemsIdentifiers can't be used with RSM (the later will be ignored if this happen)
- don't do approximative unpacking anymore in _items_rsm
- countItems and getIndex have been refactored and renamed getItemsCount and getItemsIndex, don't use query duplications anymore
- cleaned query handling in getItems
- /!\ mam module is temporarly broken
author | Goffi <goffi@goffi.org> |
---|---|
date | Sun, 03 Jan 2016 18:33:22 +0100 |
parents | 34adc4a8aa64 |
children | 29c2553ef863 |
line wrap: on
line diff
--- a/sat_pubsub/backend.py Sun Jan 03 18:33:22 2016 +0100 +++ b/sat_pubsub/backend.py Sun Jan 03 18:33:22 2016 +0100 @@ -597,28 +597,28 @@ def _doGetItems(self, result, requestor, maxItems, itemIdentifiers, ext_data): node, affiliation = result + if maxItems == 0: + log.msg("WARNING: maxItems=0 on items retrieval") + return [] def append_item_config(items_data): - ret = [] + """Add item config data form to items with roster access model""" for item_data in items_data: - item, access_model, access_list = item_data.item, item_data.access_model, item_data.config - if access_model == const.VAL_AMODEL_OPEN: + if item_data.access_model == const.VAL_AMODEL_OPEN: pass - elif access_model == const.VAL_AMODEL_ROSTER: + elif item_data.access_model == const.VAL_AMODEL_ROSTER: form = data_form.Form('submit', formNamespace=const.NS_ITEM_CONFIG) access = data_form.Field(None, const.OPT_ACCESS_MODEL, value=const.VAL_AMODEL_ROSTER) - allowed = data_form.Field(None, const.OPT_ROSTER_GROUPS_ALLOWED, values=access_list[const.OPT_ROSTER_GROUPS_ALLOWED]) + allowed = data_form.Field(None, const.OPT_ROSTER_GROUPS_ALLOWED, values=item_data.config[const.OPT_ROSTER_GROUPS_ALLOWED]) form.addField(access) form.addField(allowed) - item.addChild(form.toElement()) + item_data.item.addChild(form.toElement()) elif access_model == const.VAL_AMODEL_JID: #FIXME: manage jid raise NotImplementedError else: raise error.BadAccessTypeError(access_model) - - ret.append(item) - return ret + return items_data def access_checked(access_data): authorized, roster = access_data @@ -627,24 +627,18 @@ roster_item = roster.get(requestor.userhostJID()) authorized_groups = tuple(roster_item.groups) if roster_item else tuple() - unrestricted = affiliation == 'owner' + owner = affiliation == 'owner' if itemIdentifiers: - d = node.getItemsById(authorized_groups, unrestricted, itemIdentifiers) + d = node.getItemsById(authorized_groups, owner, itemIdentifiers) else: - d = node.getItems(authorized_groups, unrestricted, maxItems, ext_data) - if unrestricted: + d = node.getItems(authorized_groups, owner, maxItems, ext_data) + if owner: d.addCallback(append_item_config) - try: - rsm_data = ext_data['rsm'] - except KeyError: - pass - else: - if rsm_data is not None: - d.addCallback(self._items_rsm, node, authorized_groups, - unrestricted, maxItems, itemIdentifiers, - rsm_data) + d.addCallback(self._items_rsm, node, authorized_groups, + owner, itemIdentifiers, + ext_data) return d if not iidavoll.ILeafNode.providedBy(node): @@ -671,63 +665,69 @@ d.addCallback(self.checkGroup, requestor) d.addCallback(access_checked) + d.addCallback(lambda items_data: [item_data.item for item_data in items_data]) + return d def _setCount(self, value, response): response.count = value - def _setIndex(self, value, response): - response.index = value + def _setIndex(self, value, response, adjust): + """Set index in RSM response + + @param value(int): value of the reference index (i.e. before or after item) + @param response(RSMResponse): response instance to fill + @param adjust(int): adjustement term (i.e. difference between reference index and first item of the result) + """ + response.index = value + adjust - def _items_rsm(self, elts, node, authorized_groups, unrestricted, maxItems, - itemIdentifiers, request): - # FIXME: move this to a separate module ? + def _items_rsm(self, items_data, node, authorized_groups, owner, + itemIdentifiers, ext_data): + # FIXME: move this to a separate module + # TODO: Index can be optimized by keeping a cache of the last RSM request + # An other optimisation would be to look for index first and use it as offset + try: + rsm_request = ext_data['rsm'] + except KeyError: + # No RSM in this request, nothing to do + return items_data + + if itemIdentifiers: + log.msg("WARNING, itemIdentifiers used with RSM, ignoring the RSM part") + return items_data + response = rsm.RSMResponse() - d_count = node.countItems(authorized_groups, unrestricted) + d_count = node.getItemsCount(authorized_groups, owner, ext_data) d_count.addCallback(self._setCount, response) d_list = [d_count] - if request.index is not None: - response.index = request.index - elif request.before is not None: - if request.before != '': - # XXX: getIndex starts with index 1, RSM starts with 0 - d_index = node.getIndex(authorized_groups, unrestricted, request.before) - d_index.addCallback(lambda index: max(index - request.max - 1, 0)) - d_index.addCallback(self._setIndex, response) + if items_data: + response.first = items_data[0].item['id'] + response.last = items_data[-1].item['id'] + + # index handling + if rsm_request.index is not None: + response.index = rsm_request.index + elif rsm_request.before: + # The last page case (before == '') is managed in render method + d_index = node.getItemsIndex(rsm_request.before, authorized_groups, owner, ext_data) + d_index.addCallback(self._setIndex, response, -len(items_data)) d_list.append(d_index) - elif request.after is not None: - d_index = node.getIndex(authorized_groups, unrestricted, request.after) - d_index.addCallback(self._setIndex, response) - d_list.append(d_index) - elif itemIdentifiers: - d_index = node.getIndex(authorized_groups, unrestricted, itemIdentifiers[0]) - d_index.addCallback(lambda index: index - 1) - d_index.addCallback(self._setIndex, response) - d_list.append(d_index) - + elif rsm_request.after is not None: + d_index = node.getItemsIndex(rsm_request.after, authorized_groups, owner, ext_data) + d_index.addCallback(self._setIndex, response, 1) + d_list.append(d_index) + else: + # the first page was requested + response.index = 0 def render(result): - try: - items = [elt for elt in elts if elt.name == 'item'] - except AttributeError: - # XXX: see sat_pubsub.pgsql_storage.LeafNode.getItemsById return value - items = [elt[0] for elt in elts if elt[0].name == 'item'] - if len(items) > 0: - if response.index is None: - if request.before == '': # last page - response.index = response.count - request.max - else: # first page - response.index = 0 - response.first = items[0]['id'] - response.last = items[len(items) - 1]['id'] - if request.before is not None: - response.first, response.last = response.last, response.first - else: - response.index = None - elts.append(response.toElement()) - return elts + if rsm_request.before == '': + # the last page was requested + response.index = response.count - len(items_data) + items_data.append(container.ItemData(response.toElement())) + return items_data return defer.DeferredList(d_list).addCallback(render)