comparison sat_pubsub/backend.py @ 367:a772f7dac930

backend, storage(pgsql): creation/update date + serial ids: /!\ this patch updates pgqsl schema /!\ Had to set 2 features in the same patch, to avoid updating 2 times the schema. 1) creation/last modification date: column keeping the date of creation of items is renamed from "date" to "created" the date of last modification of items is saved in the new "updated" column 2) serial ids: this experimental feature allows to have ids in series (i.e. 1, 2, 3, etc.) instead of UUID. This is a convenience feature and there are some drawbacks: - PostgreSQL sequences are used, so gaps can happen (see PostgreSQL documentation for more details) - if somebody create an item with a future id in the series, the series will adapt, which can have undesired effect, and may lead to item fail if several items are created at the same time. For instance if next id in series is "8", and somebody hads already created item "8" and "256", the item will be created with biggest value in items +1 (i.e. 257). if 2 people want to create item in this situation, the second will fail with a conflict error.
author Goffi <goffi@goffi.org>
date Sat, 04 Nov 2017 21:31:32 +0100
parents 9fbb31ce495b
children 618a92080812
comparison
equal deleted inserted replaced
366:81e6d4a516c3 367:a772f7dac930
140 const.VAL_PMODEL_OPEN: "Everybody can publish", 140 const.VAL_PMODEL_OPEN: "Everybody can publish",
141 const.VAL_PMODEL_PUBLISHERS: "Only owner and publishers can publish", 141 const.VAL_PMODEL_PUBLISHERS: "Only owner and publishers can publish",
142 const.VAL_PMODEL_SUBSCRIBERS: "Everybody which subscribed to the node", 142 const.VAL_PMODEL_SUBSCRIBERS: "Everybody which subscribed to the node",
143 } 143 }
144 }, 144 },
145 const.OPT_SERIAL_IDS:
146 {"type": "boolean",
147 "label": "Use serial ids"},
145 } 148 }
146 149
147 subscriptionOptions = { 150 subscriptionOptions = {
148 "pubsub#subscription_type": 151 "pubsub#subscription_type":
149 {"type": "list-single", 152 {"type": "list-single",
356 #FIXME: owner and publisher are not necessarly the same. So far we use only owner to get roster. 359 #FIXME: owner and publisher are not necessarly the same. So far we use only owner to get roster.
357 #FIXME: in addition, there can be several owners: that is not managed yet 360 #FIXME: in addition, there can be several owners: that is not managed yet
358 d.addCallback(self._doPublish, items, requestor, pep, recipient) 361 d.addCallback(self._doPublish, items, requestor, pep, recipient)
359 return d 362 return d
360 363
364 @defer.inlineCallbacks
361 def _doPublish(self, result, items, requestor, pep, recipient): 365 def _doPublish(self, result, items, requestor, pep, recipient):
362 affiliation, node = result 366 affiliation, node = result
363 if node.nodeType == 'collection': 367 if node.nodeType == 'collection':
364 raise error.NoPublishing() 368 raise error.NoPublishing()
365 369
379 item['publisher'] = requestor.full() 383 item['publisher'] = requestor.full()
380 if persistItems or deliverPayloads: 384 if persistItems or deliverPayloads:
381 item.uri = None 385 item.uri = None
382 item.defaultUri = None 386 item.defaultUri = None
383 if not item.getAttribute("id"): 387 if not item.getAttribute("id"):
384 item["id"] = str(uuid.uuid4()) 388 item["id"] = yield node.getNextId()
389 new_item = True
385 else: 390 else:
386 check_overwrite = True 391 check_overwrite = True
392 new_item = False
387 access_model, item_config = self.parseItemConfig(item) 393 access_model, item_config = self.parseItemConfig(item)
388 categories = self.parseCategories(item) 394 categories = self.parseCategories(item)
389 schema = node.getSchema() 395 schema = node.getSchema()
390 if schema is not None: 396 if schema is not None:
391 self.enforceSchema(item, schema, affiliation) 397 self.enforceSchema(item, schema, affiliation)
392 items_data.append(container.ItemData(item, access_model, item_config, categories)) 398 items_data.append(container.ItemData(item, access_model, item_config, categories, new=new_item))
393 399
394 if persistItems: 400 if persistItems:
401
395 if check_overwrite and affiliation != 'owner': 402 if check_overwrite and affiliation != 'owner':
396 # we don't want a publisher to overwrite the item 403 # we don't want a publisher to overwrite the item
397 # of an other publisher 404 # of an other publisher
398 d = self._checkOverwrite(node, [item['id'] for item in items if item.getAttribute('id')], requestor) 405 yield self._checkOverwrite(node, [item['id'] for item in items if item.getAttribute('id')], requestor)
399 d.addCallback(lambda _: node.storeItems(items_data, requestor)) 406
400 else: 407 # TODO: check conflict and recalculate max id if serial_ids is set
401 d = node.storeItems(items_data, requestor) 408 yield node.storeItems(items_data, requestor)
402 else: 409
403 d = defer.succeed(None) 410 yield self._doNotify(node, items_data, deliverPayloads, pep, recipient)
404 411
405 d.addCallback(self._doNotify, node, items_data, 412 def _doNotify(self, node, items_data, deliverPayloads, pep, recipient):
406 deliverPayloads, pep, recipient)
407 return d
408
409 def _doNotify(self, result, node, items_data, deliverPayloads, pep, recipient):
410 if items_data and not deliverPayloads: 413 if items_data and not deliverPayloads:
411 for item_data in items_data: 414 for item_data in items_data:
412 item_data.item.children = [] 415 item_data.item.children = []
413 self.dispatch({'items_data': items_data, 'node': node, 'pep': pep, 'recipient': recipient}, 416 self.dispatch({'items_data': items_data, 'node': node, 'pep': pep, 'recipient': recipient},
414 '//event/pubsub/notify') 417 '//event/pubsub/notify')
619 622
620 d = self.storage.getNode(nodeIdentifier, pep, recipient) 623 d = self.storage.getNode(nodeIdentifier, pep, recipient)
621 d.addCallback(lambda node: node.getSchema()) 624 d.addCallback(lambda node: node.getSchema())
622 625
623 return d 626 return d
624
625 627
626 def setNodeSchema(self, nodeIdentifier, schema, requestor, pep, recipient): 628 def setNodeSchema(self, nodeIdentifier, schema, requestor, pep, recipient):
627 """set or remove Schema of a node 629 """set or remove Schema of a node
628 630
629 @param nodeIdentifier(unicode): identifier of the pubusb node 631 @param nodeIdentifier(unicode): identifier of the pubusb node