def denormalizer(msg): oid = msg.get("_id") age = now - utils.oid_ts(oid) return { "id": str(oid), "age": age, "ttl": msg["t"], "body": msg["b"], "marker": str(oid), }
def denormalizer(messages): for msg in messages: ttl = int(msg["ttl"]) oid = objectid.ObjectId() ids.append(str(oid)) # Lets remove the timezone, we want it to be plain # utc expires = utils.oid_ts(oid) + ttl yield { "_id": oid, "t": ttl, "q": qid, "e": expires, "u": client_uuid, "c": {"id": None, "e": 0}, "b": msg['body'] if 'body' in msg else {} }
def update(self, queue, claim_id, metadata, tenant=None): cid = utils.to_oid(claim_id) now = timeutils.utcnow_ts() ttl = int(metadata.get("ttl", 60)) # Lets remove the timezone, # we want it to be plain utc expires = utils.oid_ts(cid) + ttl if now > expires: msg = _("New ttl will make the claim expires") raise ValueError(msg) qid = self._get_queue_id(queue, tenant) msg_ctrl = self.driver.message_controller claimed = msg_ctrl.claimed(qid, cid, expires=now, limit=1) try: claimed.next() except StopIteration: raise exceptions.ClaimDoesNotExist(cid, queue, tenant) meta = { "id": cid, "t": ttl, "e": expires, } msg_ctrl._col.update({"q": qid, "c.id": cid}, {"$set": {"c": meta}}, upsert=False, multi=True) # NOTE(flaper87): Dirty hack! # This sets the expiration time to # `expires` on messages that would # expire before claim. msg_ctrl._col.update({"q": qid, "e": {"$lte": expires}, "c.id": cid}, {"$set": {"e": expires}}, upsert=False, multi=True)
def get(self, queue, claim_id, tenant=None): msg_ctrl = self.driver.message_controller # Check whether the queue exists or not qid = self._get_queue_id(queue, tenant) # Base query, always check expire time now = timeutils.utcnow_ts() cid = utils.to_oid(claim_id) age = now - utils.oid_ts(cid) def messages(msg_iter): msg = msg_iter.next() yield msg.pop("claim") yield msg # Smoke it! for msg in msg_iter: del msg["claim"] yield msg try: # Lets get claim's data # from the first message # in the iterator messages = messages(msg_ctrl.claimed(qid, cid, now)) claim = messages.next() claim = { "age": age, "ttl": claim.pop("t"), "id": str(claim.pop("id")), } except StopIteration: raise exceptions.ClaimDoesNotExist(cid, queue, tenant) return (claim, messages)
def get(self, queue, message_id, tenant=None): # Base query, always check expire time mid = utils.to_oid(message_id) query = { "q": self._get_queue_id(queue, tenant), "e": {"$gt": timeutils.utcnow_ts()}, "_id": mid } message = self._col.find_one(query) if message is None: raise exceptions.MessageDoesNotExist(mid, queue, tenant) oid = message.get("_id") age = timeutils.utcnow_ts() - utils.oid_ts(oid) return { "id": oid, "age": age, "ttl": message["t"], "body": message["b"], }
def create(self, queue, metadata, tenant=None, limit=10): """ This implementation was done in a best-effort fashion. In order to create a claim we need to get a list of messages that can be claimed. Once we have that list we execute a query filtering by the ids returned by the previous query. Since there's a lot of space for race conditions here, we'll check if the number of updated records is equal to the max number of messages to claim. If the number of updated messages is lower than limit we'll try to claim the remaining number of messages. This 2 queries are required because there's no way, as for the time being, to executed an update on a limited number of records """ msg_ctrl = self.driver.message_controller # We don't need the qid here but # we need to verify it exists. qid = self._get_queue_id(queue, tenant) ttl = int(metadata.get("ttl", 60)) oid = objectid.ObjectId() # Lets remove the timezone, # we want it to be plain utc expires = utils.oid_ts(oid) + ttl meta = { "id": oid, "t": ttl, "e": expires, } # Get a list of active, not claimed nor expired # messages that could be claimed. msgs = msg_ctrl.active(qid, fields={"_id": 1}) msgs = msgs.limit(limit).sort("_id") messages = iter([]) # Lets respect the limit # during the count if msgs.count(True) == 0: return (str(oid), messages) ids = [msg["_id"] for msg in msgs] now = timeutils.utcnow_ts() # Set claim field for messages in ids updated = msg_ctrl._col.update({"_id": {"$in": ids}, "$or": [ {"c.id": None}, { "c.id": {"$ne": None}, "c.e": {"$lte": now} } ]}, {"$set": {"c": meta}}, upsert=False, multi=True)["n"] # NOTE(flaper87): Dirty hack! # This sets the expiration time to # `expires` on messages that would # expire before claim. msg_ctrl._col.update({"q": queue, "e": {"$lte": expires}, "c.id": oid}, {"$set": {"e": expires}}, upsert=False, multi=True) if updated != 0: claim, messages = self.get(queue, oid, tenant=tenant) return (str(oid), messages)