Mercurial > libervia-pubsub
diff sat_pubsub/pgsql_storage.py @ 422:c21f31355ab9
configuration: "max_items" option:
"max_items" is implemented using a text-single field, as it is done in the XEP-0060
example (there is no real formal description). When changing the node configuration, the
max_items can't be set to a number lower than the total number of items in the node (the
configuration will then be rejected), this is to avoid accidental deletion of items.
author | Goffi <goffi@goffi.org> |
---|---|
date | Tue, 10 Mar 2020 11:11:38 +0100 |
parents | ccb2a22ea0fc |
children | 3fce48c0a44d |
line wrap: on
line diff
--- a/sat_pubsub/pgsql_storage.py Sat Feb 22 13:06:51 2020 +0100 +++ b/sat_pubsub/pgsql_storage.py Tue Mar 10 11:11:38 2020 +0100 @@ -109,6 +109,7 @@ defaultConfig = { 'leaf': { const.OPT_PERSIST_ITEMS: True, + const.OPT_MAX_ITEMS: 'max', const.OPT_DELIVER_PAYLOADS: True, const.OPT_SEND_LAST_PUBLISHED_ITEM: 'on_sub', const.OPT_ACCESS_MODEL: const.VAL_AMODEL_DEFAULT, @@ -142,22 +143,21 @@ def _buildNode(self, row): """Build a note class from database result row""" - configuration = {} - if not row: raise error.NodeNotFound() if row[2] == 'leaf': configuration = { - 'pubsub#persist_items': row[3], - 'pubsub#deliver_payloads': row[4], - 'pubsub#send_last_published_item': row[5], - const.OPT_ACCESS_MODEL:row[6], - const.OPT_PUBLISH_MODEL:row[7], - const.OPT_SERIAL_IDS:row[8], - const.OPT_CONSISTENT_PUBLISHER:row[9], + const.OPT_PERSIST_ITEMS: row[3], + const.OPT_MAX_ITEMS: 'max' if row[4] == 0 else str(row[4]), + const.OPT_DELIVER_PAYLOADS: row[5], + const.OPT_SEND_LAST_PUBLISHED_ITEM: row[6], + const.OPT_ACCESS_MODEL:row[7], + const.OPT_PUBLISH_MODEL:row[8], + const.OPT_SERIAL_IDS:row[9], + const.OPT_CONSISTENT_PUBLISHER:row[10], } - schema = row[10] + schema = row[11] if schema is not None: schema = parseXml(schema) node = LeafNode(row[0], row[1], configuration, schema) @@ -165,10 +165,10 @@ return node elif row[2] == 'collection': configuration = { - 'pubsub#deliver_payloads': row[4], - 'pubsub#send_last_published_item': row[5], - const.OPT_ACCESS_MODEL: row[6], - const.OPT_PUBLISH_MODEL:row[7], + const.OPT_DELIVER_PAYLOADS: row[5], + const.OPT_SEND_LAST_PUBLISHED_ITEM: row[6], + const.OPT_ACCESS_MODEL: row[7], + const.OPT_PUBLISH_MODEL:row[8], } node = CollectionNode(row[0], row[1], configuration, None) node.dbpool = self.dbpool @@ -188,6 +188,7 @@ node, node_type, persist_items, + max_items, deliver_payloads, send_last_published_item, access_model, @@ -210,6 +211,7 @@ node, node_type, persist_items, + max_items, deliver_payloads, send_last_published_item, access_model, @@ -537,6 +539,7 @@ self._checkNodeExists(cursor) self._configurationTriggers(cursor, self.nodeDbId, self._config, config) cursor.execute("""UPDATE nodes SET persist_items=%s, + max_items=%s, deliver_payloads=%s, send_last_published_item=%s, access_model=%s, @@ -545,6 +548,7 @@ consistent_publisher=%s WHERE node_id=%s""", (config[const.OPT_PERSIST_ITEMS], + config[const.OPT_MAX_ITEMS], config[const.OPT_DELIVER_PAYLOADS], config[const.OPT_SEND_LAST_PUBLISHED_ITEM], config[const.OPT_ACCESS_MODEL], @@ -951,7 +955,8 @@ if access_model == const.VAL_AMODEL_PUBLISHER_ROSTER: if const.OPT_ROSTER_GROUPS_ALLOWED in item_config: - item_config.fields[const.OPT_ROSTER_GROUPS_ALLOWED].fieldType='list-multi' #XXX: needed to force list if there is only one value + # XXX: needed to force list if there is only one value + item_config.fields[const.OPT_ROSTER_GROUPS_ALLOWED].fieldType='list-multi' allowed_groups = item_config[const.OPT_ROSTER_GROUPS_ALLOWED] else: allowed_groups = [] @@ -961,6 +966,24 @@ VALUES (%s,%s)""" , (item_id, group)) # TODO: whitelist access model + max_items = self._config.get(const.OPT_MAX_ITEMS, 'max') + + if max_items != 'max': + try: + max_items = int(self._config[const.OPT_MAX_ITEMS]) + except ValueError: + log.err(f"Invalid max_items value: {max_items!r}") + else: + if max_items > 0: + # we delete all items above the requested max + cursor.execute( + "DELETE FROM items WHERE node_id=%s and item_id in (SELECT " + "item_id FROM items WHERE node_id=%s ORDER BY items.updated " + "DESC, items.item_id DESC OFFSET %s)" , + (self.nodeDbId, self.nodeDbId, max_items) + ) + + def _storeCategories(self, cursor, item_id, categories, update=False): # TODO: handle canonical form if update: