Пример #1
0
    def update(self, queue, claim_id, metadata, project=None):
        if project is None:
            project = ''

        cid = utils.cid_decode(claim_id)
        if cid is None:
            raise errors.ClaimDoesNotExist(claim_id, queue, project)

        age = utils.get_age(tables.Claims.c.created)
        with self.driver.trans() as trans:
            qid = utils.get_qid(self.driver, queue, project)

            update = tables.Claims.update().where(sa.and_(
                tables.Claims.c.ttl > age,
                tables.Claims.c.id == cid,
                tables.Claims.c.id == qid)).\
                values(ttl=metadata['ttl'])

            res = trans.execute(update)
            if res.rowcount != 1:
                raise errors.ClaimDoesNotExist(claim_id, queue, project)

            update = (tables.Messages.update().values(
                ttl=metadata['ttl']).where(
                    sa.and_(tables.Messages.c.ttl < metadata['ttl'],
                            tables.Messages.c.cid == cid)))
            trans.execute(update)
Пример #2
0
    def update(self, queue, claim_id, metadata, project=None):
        if project is None:
            project = ''

        cid = utils.cid_decode(claim_id)
        if cid is None:
            raise errors.ClaimDoesNotExist(claim_id, queue, project)

        age = utils.get_age(tables.Claims.c.created)
        with self.driver.trans() as trans:
            qid = utils.get_qid(self.driver, queue, project)

            update = tables.Claims.update().where(sa.and_(
                tables.Claims.c.ttl > age,
                tables.Claims.c.id == cid,
                tables.Claims.c.id == qid)).\
                values(ttl=metadata['ttl'])

            res = trans.execute(update)
            if res.rowcount != 1:
                raise errors.ClaimDoesNotExist(claim_id, queue, project)

            update = (tables.Messages.update().
                      values(ttl=metadata['ttl']).
                      where(sa.and_(
                          tables.Messages.c.ttl < metadata['ttl'],
                          tables.Messages.c.cid == cid)))
            trans.execute(update)
Пример #3
0
    def post(self, queue, messages, client_uuid, project):
        if project is None:
            project = ''

        with self.driver.trans() as trans:
            qid = utils.get_qid(self.driver, queue, project)

            # cleanup all expired messages in this queue
            #self.driver.run('''
            #    delete from Messages
            #     where ttl <= julianday() * 86400.0 - created
            #       and qid = ?''', qid)

            # executemany() sets lastrowid to None, so no matter we manually
            # generate the IDs or not, we still need to query for it.

            def it():
                for m in messages:
                    yield dict(qid=qid,
                               ttl=m['ttl'],
                               body=json.dumps(m['body']),
                               client=str(client_uuid))

            result = trans.execute(tables.Messages.insert(), list(it()))

            statement = sa.sql.select([tables.Messages.c.id])
            statement = statement.limit(result.rowcount)
            statement = statement.order_by(tables.Messages.c.id.desc())
            result = trans.execute(statement).fetchall()

        return map(utils.msgid_encode, [i[0] for i in reversed(result)])
Пример #4
0
    def delete(self, queue, claim_id, project=None):
        if project is None:
            project = ''

        cid = utils.cid_decode(claim_id)
        if cid is None:
            return

        with self.driver.trans() as trans:
            try:
                # NOTE(flaper87): This could probably use some
                # joins and be just 1 query.
                qid = utils.get_qid(self.driver, queue, project)
            except errors.QueueDoesNotExist:
                return

            and_stmt = sa.and_(tables.Claims.c.id == cid,
                               tables.Claims.c.qid == qid)
            dlt = tables.Claims.delete().where(and_stmt)
            trans.execute(dlt)

            update = (tables.Messages.update().values(cid=None).
                      where(tables.Messages.c.cid == cid))

            trans.execute(update)
Пример #5
0
    def delete(self, queue, claim_id, project=None):
        if project is None:
            project = ''

        cid = utils.cid_decode(claim_id)
        if cid is None:
            return

        with self.driver.trans() as trans:
            try:
                # NOTE(flaper87): This could probably use some
                # joins and be just 1 query.
                qid = utils.get_qid(self.driver, queue, project)
            except errors.QueueDoesNotExist:
                return

            and_stmt = sa.and_(tables.Claims.c.id == cid,
                               tables.Claims.c.qid == qid)
            dlt = tables.Claims.delete().where(and_stmt)
            trans.execute(dlt)

            update = (tables.Messages.update().values(cid=None).
                      where(tables.Messages.c.cid == cid))

            trans.execute(update)
Пример #6
0
    def pop(self, queue_name, limit, project=None):
        if project is None:
            project = ''

        with self.driver.trans() as trans:
            sel = sa.sql.select([
                tables.Messages.c.id, tables.Messages.c.body,
                tables.Messages.c.ttl, tables.Messages.c.created
            ])

            j = sa.join(tables.Messages, tables.Queues,
                        tables.Messages.c.qid == tables.Queues.c.id)

            sel = sel.select_from(j)
            and_clause = [
                tables.Queues.c.name == queue_name,
                tables.Queues.c.project == project
            ]

            and_clause.append(tables.Messages.c.cid == (None))

            sel = sel.where(sa.and_(*and_clause))
            sel = sel.limit(limit)

            records = trans.execute(sel)
            now = timeutils.utcnow_ts()
            messages = []
            message_ids = []
            for id, body, ttl, created in records:
                messages.append({
                    'id':
                    utils.msgid_encode(id),
                    'ttl':
                    ttl,
                    'age':
                    now - calendar.timegm(created.timetuple()),
                    'body':
                    utils.json_decode(body),
                })
                message_ids.append(id)

            statement = tables.Messages.delete()

            qid = utils.get_qid(self.driver, queue_name, project)

            and_stmt = [
                tables.Messages.c.id.in_(message_ids),
                tables.Messages.c.qid == qid
            ]

            trans.execute(statement.where(sa.and_(*and_stmt)))

            return messages
Пример #7
0
    def create(self,
               queue,
               metadata,
               project=None,
               limit=storage.DEFAULT_MESSAGES_PER_CLAIM):

        if project is None:
            project = ''

        with self.driver.trans() as trans:
            try:
                qid = utils.get_qid(self.driver, queue, project)
            except errors.QueueDoesNotExist:
                return None, iter([])

            # Clean up all expired claims in this queue

            dlt = tables.Claims.delete().where(
                sa.and_(
                    tables.Claims.c.ttl <= utils.get_age(
                        tables.Claims.c.created), tables.Claims.c.qid == qid))
            trans.execute(dlt)

            ins = tables.Claims.insert().values(qid=qid, ttl=metadata['ttl'])
            res = trans.execute(ins)

            cid = res.lastrowid

            and_stmt = sa.and_(
                tables.Messages.c.cid == (None), tables.Messages.c.ttl >
                sfunc.now() - tables.Messages.c.created,
                tables.Messages.c.qid == qid)
            sel = sa.sql.select([tables.Messages.c.id], and_stmt).limit(limit)

            records = [t[0] for t in trans.execute(sel)]
            and_stmt = sa.and_(tables.Messages.c.id.in_(records))
            update = tables.Messages.update().values(cid=cid).where(and_stmt)
            trans.execute(update)

            # NOTE(flaper87): I bet there's a better way
            # to do this.
            messages_ttl = metadata['ttl'] + metadata['grace']
            update = (tables.Messages.update().values(ttl=messages_ttl).where(
                sa.and_(tables.Messages.c.ttl < messages_ttl,
                        tables.Messages.c.cid == cid)))
            trans.execute(update)

            return (utils.cid_encode(cid), self.__get(cid))
Пример #8
0
    def create(self, queue, metadata, project=None,
               limit=storage.DEFAULT_MESSAGES_PER_CLAIM):

        if project is None:
            project = ''

        with self.driver.trans() as trans:
            try:
                qid = utils.get_qid(self.driver, queue, project)
            except errors.QueueDoesNotExist:
                return None, iter([])

            # Clean up all expired claims in this queue

            dlt = tables.Claims.delete().where(sa.and_(
                tables.Claims.c.ttl <=
                utils.get_age(tables.Claims.c.created),
                tables.Claims.c.qid == qid))
            trans.execute(dlt)

            ins = tables.Claims.insert().values(qid=qid, ttl=metadata['ttl'])
            res = trans.execute(ins)

            cid = res.lastrowid

            and_stmt = sa.and_(tables.Messages.c.cid == (None),
                               tables.Messages.c.ttl >
                               sfunc.now() - tables.Messages.c.created,
                               tables.Messages.c.qid == qid)
            sel = sa.sql.select([tables.Messages.c.id], and_stmt).limit(limit)

            records = [t[0] for t in trans.execute(sel)]
            and_stmt = sa.and_(tables.Messages.c.id.in_(records))
            update = tables.Messages.update().values(cid=cid).where(and_stmt)
            trans.execute(update)

            # NOTE(flaper87): I bet there's a better way
            # to do this.
            messages_ttl = metadata['ttl'] + metadata['grace']
            update = (tables.Messages.update().values(ttl=messages_ttl).
                      where(sa.and_(
                          tables.Messages.c.ttl < messages_ttl,
                          tables.Messages.c.cid == cid)))
            trans.execute(update)

            return (utils.cid_encode(cid), self.__get(cid))
Пример #9
0
    def pop(self, queue_name, limit, project=None):
        if project is None:
            project = ''

        with self.driver.trans() as trans:
            sel = sa.sql.select([tables.Messages.c.id,
                                 tables.Messages.c.body,
                                 tables.Messages.c.ttl,
                                 tables.Messages.c.created])

            j = sa.join(tables.Messages, tables.Queues,
                        tables.Messages.c.qid == tables.Queues.c.id)

            sel = sel.select_from(j)
            and_clause = [tables.Queues.c.name == queue_name,
                          tables.Queues.c.project == project]

            and_clause.append(tables.Messages.c.cid == (None))

            sel = sel.where(sa.and_(*and_clause))
            sel = sel.limit(limit)

            records = trans.execute(sel)
            now = timeutils.utcnow_ts()
            messages = []
            message_ids = []
            for id, body, ttl, created in records:
                messages.append({
                    'id': utils.msgid_encode(id),
                    'ttl': ttl,
                    'age': now - calendar.timegm(created.timetuple()),
                    'body': utils.json_decode(body),
                })
                message_ids.append(id)

            statement = tables.Messages.delete()

            qid = utils.get_qid(self.driver, queue_name, project)

            and_stmt = [tables.Messages.c.id.in_(message_ids),
                        tables.Messages.c.qid == qid]

            trans.execute(statement.where(sa.and_(*and_stmt)))

            return messages
Пример #10
0
    def bulk_delete(self, queue, message_ids, project):
        if project is None:
            project = ''

        message_ids = ','.join(
            ["'%s'" % id for id in
             map(utils.msgid_decode, message_ids) if id]
        )

        with self.driver.trans() as trans:
            qid = utils.get_qid(self.driver, queue, project)

            statement = tables.Messages.delete()

            and_stmt = [tables.Messages.c.id.in_(message_ids),
                        tables.Messages.c.qid == qid]

            trans.execute(statement.where(sa.and_(*and_stmt)))
Пример #11
0
    def stats(self, name, project):
        if project is None:
            project = ''

        qid = utils.get_qid(self.driver, name, project)
        sel = sa.sql.select([
            sa.sql.select([sa.func.count(tables.Messages.c.id)],
                          sa.and_(
                              tables.Messages.c.qid == qid,
                              tables.Messages.c.cid != (None),
                              tables.Messages.c.ttl >
                              sfunc.now() - tables.Messages.c.created,
                          )),
            sa.sql.select([sa.func.count(tables.Messages.c.id)],
                          sa.and_(
                              tables.Messages.c.qid == qid,
                              tables.Messages.c.cid == (None),
                              tables.Messages.c.ttl >
                              sfunc.now() - tables.Messages.c.created,
                          ))
        ])

        claimed, free = self.driver.get(sel)

        total = free + claimed

        message_stats = {
            'claimed': claimed,
            'free': free,
            'total': total,
        }

        try:
            message_controller = self.driver.message_controller
            oldest = message_controller.first(name, project, sort=1)
            newest = message_controller.first(name, project, sort=-1)
        except errors.QueueIsEmpty:
            pass
        else:
            message_stats['oldest'] = utils.stat_message(oldest)
            message_stats['newest'] = utils.stat_message(newest)

        return {'messages': message_stats}
Пример #12
0
    def delete(self, queue, claim_id, project=None):
        if project is None:
            project = ''

        cid = utils.cid_decode(claim_id)
        if cid is None:
            return

        with self.driver.trans() as trans:
            qid = utils.get_qid(self.driver, queue, project)
            and_stmt = sa.and_(tables.Claims.c.id == cid,
                               tables.Claims.c.qid == qid)
            dlt = tables.Claims.delete().where(and_stmt)
            trans.execute(dlt)

            update = (tables.Messages.update().values(cid=None).where(
                tables.Messages.c.cid == cid))

            trans.execute(update)
Пример #13
0
    def stats(self, name, project):
        if project is None:
            project = ''

        qid = utils.get_qid(self.driver, name, project)
        sel = sa.sql.select([
            sa.sql.select([sa.func.count(tables.Messages.c.id)],
                          sa.and_(
                              tables.Messages.c.qid == qid,
                              tables.Messages.c.cid != (None),
                              tables.Messages.c.ttl >
                              sfunc.now() - tables.Messages.c.created,
                          )),
            sa.sql.select([sa.func.count(tables.Messages.c.id)],
                          sa.and_(
                              tables.Messages.c.qid == qid,
                              tables.Messages.c.cid == (None),
                              tables.Messages.c.ttl >
                              sfunc.now() - tables.Messages.c.created,
                          ))
        ])

        claimed, free = self.driver.get(sel)

        total = free + claimed

        message_stats = {
            'claimed': claimed,
            'free': free,
            'total': total,
        }

        try:
            message_controller = self.driver.message_controller
            oldest = message_controller.first(name, project, sort=1)
            newest = message_controller.first(name, project, sort=-1)
        except errors.QueueIsEmpty:
            pass
        else:
            message_stats['oldest'] = utils.stat_message(oldest)
            message_stats['newest'] = utils.stat_message(newest)

        return {'messages': message_stats}
Пример #14
0
    def bulk_delete(self, queue, message_ids, project):
        if project is None:
            project = ''

        message_ids = [id for id in
                       map(utils.msgid_decode, message_ids) if id]

        with self.driver.trans() as trans:
            try:
                qid = utils.get_qid(self.driver, queue, project)
            except errors.QueueDoesNotExist:
                return

            statement = tables.Messages.delete()

            and_stmt = [tables.Messages.c.id.in_(message_ids),
                        tables.Messages.c.qid == qid]

            trans.execute(statement.where(sa.and_(*and_stmt)))
Пример #15
0
    def delete(self, queue, claim_id, project=None):
        if project is None:
            project = ''

        cid = utils.cid_decode(claim_id)
        if cid is None:
            return

        with self.driver.trans() as trans:
            qid = utils.get_qid(self.driver, queue, project)
            and_stmt = sa.and_(tables.Claims.c.id == cid,
                               tables.Claims.c.qid == qid)
            dlt = tables.Claims.delete().where(and_stmt)
            trans.execute(dlt)

            update = (tables.Messages.update().values(cid=None).
                      where(tables.Messages.c.cid == cid))

            trans.execute(update)
Пример #16
0
    def bulk_delete(self, queue, message_ids, project):
        if project is None:
            project = ''

        message_ids = [id for id in map(utils.msgid_decode, message_ids) if id]

        with self.driver.trans() as trans:
            try:
                qid = utils.get_qid(self.driver, queue, project)
            except errors.QueueDoesNotExist:
                return

            statement = tables.Messages.delete()

            and_stmt = [
                tables.Messages.c.id.in_(message_ids),
                tables.Messages.c.qid == qid
            ]

            trans.execute(statement.where(sa.and_(*and_stmt)))
Пример #17
0
    def first(self, queue, project=None, sort=1):
        if project is None:
            project = ''

        qid = utils.get_qid(self.driver, queue, project)

        sel = sa.sql.select([tables.Messages.c.id,
                             tables.Messages.c.body,
                             tables.Messages.c.ttl,
                             tables.Messages.c.created],
                            sa.and_(
                                tables.Messages.c.ttl >
                                sfunc.now() - tables.Messages.c.created,
                                tables.Messages.c.qid == qid))
        if sort not in (1, -1):
            raise ValueError(u'sort must be either 1 (ascending) '
                             u'or -1 (descending)')

        order = sa.asc
        if sort == -1:
            order = sa.desc

        sel = sel.order_by(order(tables.Messages.c.id))

        try:
            id, body, ttl, created = self.driver.get(sel)
        except utils.NoResult:
            raise errors.QueueIsEmpty(queue, project)

        created_iso = timeutils.isotime(created)
        return {
            'id': utils.msgid_encode(id),
            'ttl': ttl,
            'created': created_iso,
            'age': int((timeutils.utcnow() - created).seconds),
            'body': body,
        }