changeset 375:9a787881b824

implemented Order-By ProtoXEP (MAM + PubSub)
author Goffi <goffi@goffi.org>
date Sun, 06 Jan 2019 17:29:50 +0100
parents 40e5edd7ea11
children b80f7848d8a2
files src/backend.py src/mam.py src/pgsql_storage.py src/twisted/plugins/pubsub.py
diffstat 4 files changed, 52 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/src/backend.py	Thu Jan 03 20:31:03 2019 +0100
+++ b/src/backend.py	Sun Jan 06 17:29:50 2019 +0100
@@ -77,6 +77,7 @@
 from wokkel import rsm
 from wokkel import iwokkel
 from wokkel import pubsub
+from wokkel.subprotocols import XMPPHandler
 
 from sat_pubsub import error
 from sat_pubsub import iidavoll
@@ -1663,6 +1664,7 @@
             ext_data['pep'] = request.delegated
         except AttributeError:
             pass
+        ext_data['order_by'] = request.orderBy or []
         d = self.backend.getItems(request.nodeIdentifier,
                                   request.sender,
                                   request.recipient,
@@ -1697,3 +1699,16 @@
 components.registerAdapter(PubSubResourceFromBackend,
                            iidavoll.IBackendService,
                            iwokkel.IPubSubResource)
+
+
+
+class ExtraDiscoHandler(XMPPHandler):
+    implements(iwokkel.IDisco)
+    # see comment in twisted/plugins/pubsub.py
+    # FIXME: upstream must be fixed so we can use custom (non pubsub#) disco features
+
+    def getDiscoInfo(self, requestor, service, nodeIdentifier=''):
+        return [disco.DiscoFeature(pubsub.NS_ORDER_BY)]
+
+    def getDiscoItems(self, requestor, service, nodeIdentifier=''):
+        return []
--- a/src/mam.py	Thu Jan 03 20:31:03 2019 +0100
+++ b/src/mam.py	Sun Jan 06 17:29:50 2019 +0100
@@ -85,6 +85,9 @@
         else:
             ext_data['rsm'] = mam_request.rsm
 
+        if mam_request.orderBy:
+            ext_data['order_by'] = mam_request.orderBy
+
         d = self.backend.getItemsData(mam_request.node, mam_request.sender, mam_request.recipient, None, None, ext_data)
 
         def make_message(elt):
--- a/src/pgsql_storage.py	Thu Jan 03 20:31:03 2019 +0100
+++ b/src/pgsql_storage.py	Sun Jan 06 17:29:50 2019 +0100
@@ -834,6 +834,29 @@
 
     nodeType = 'leaf'
 
+    def getOrderBy(self, ext_data, direction='DESC'):
+        """Return ORDER BY clause corresponding to Order By key in ext_data
+
+        @param ext_data (dict): extra data as used in getItems
+        @param direction (unicode): ORDER BY direction (ASC or DESC)
+        @return (unicode): ORDER BY clause to use
+        """
+        keys = ext_data.get('order_by')
+        if not keys:
+            return u'ORDER BY items.updated ' + direction
+        cols_statmnt = []
+        for key in keys:
+            if key == 'creation':
+                column = 'items.item_id'  # could work with items.created too
+            elif key == 'modification':
+                column = 'items.updated'
+            else:
+                log.msg(u"WARNING: Unknown order by key: {key}".format(key=key))
+                column = 'items.updated'
+            cols_statmnt.append(column + u' ' + direction)
+
+        return u"ORDER BY " + u",".join([col for col in cols_statmnt])
+
     def storeItems(self, item_data, publisher):
         return self.dbpool.runInteraction(self._storeItems, item_data, publisher)
 
@@ -1031,7 +1054,7 @@
 
         query.extend(query_filters)
 
-        return "ORDER BY items.updated DESC"
+        return self.getOrderBy(ext_data)
 
     def _getItems(self, cursor, authorized_groups, unrestricted, maxItems, ext_data, ids_only):
         self._checkNodeExists(cursor)
@@ -1075,7 +1098,8 @@
                     # if we have maxItems (i.e. a limit), we need to reverse order
                     # in a first query to get the right items
                     query.insert(0,"SELECT * from (")
-                    query.append("ORDER BY updated ASC LIMIT %s) as x")
+                    query.append(self.getOrderBy(ext_data, direction='ASC'))
+                    query.append("LIMIT %s) as x")
                     args.append(maxItems)
             elif rsm.after:
                 query.append("AND item_id<(SELECT item_id FROM items WHERE item=%s LIMIT 1)")
--- a/src/twisted/plugins/pubsub.py	Thu Jan 03 20:31:03 2019 +0100
+++ b/src/twisted/plugins/pubsub.py	Sun Jan 06 17:29:50 2019 +0100
@@ -69,7 +69,7 @@
 
 from sat_pubsub import const
 from sat_pubsub import mam as pubsub_mam
-from sat_pubsub.backend import BackendService
+from sat_pubsub.backend import BackendService, ExtraDiscoHandler
 from sat_pubsub.schema import SchemaHandler
 from sat_pubsub.privilege import PrivilegesHandler
 from sat_pubsub.delegation import DelegationsHandler
@@ -231,6 +231,13 @@
         sh = SchemaHandler()
         sh.setHandlerParent(cs)
 
+        # wokkel.pubsub doesn't handle non pubsub# disco
+        # and we need to announce other feature, so this is a workaround
+        # to add them
+        # FIXME: propose a patch upstream to fix this situation
+        ed = ExtraDiscoHandler()
+        ed.setHandlerParent(cs)
+
         # XXX: delegation must be instancied at the end,
         #      because it does some MonkeyPatching on handlers
         dh = DelegationsHandler()