예제 #1
0
 def stats(self):
     cmd = """
         select value, count(*) as count
         from attributes
         where kind=%s and attribute="topic"
         group by value
         """
     kind = EntityStore(self.db, Message).kind
     return self.db(cmd, kind)
예제 #2
0
 def topics(self):
     cmd = """
         select distinct value
         from attributes
         where kind=%s and attribute="topic"
         order by value
         """
     kind = EntityStore(self.db, Message).kind
     return [a for a, in self.db(cmd, kind)]
예제 #3
0
    def __init__(self, store, config, context):
        from .store import EntityStore
        self.db = store.db

        self.application_settings_store = EntityStore(self.db,
                                                      ApplicationSettings)
        self._application_dict = {
            p.key: p.value
            for p in self.application_settings_store
        }

        self.user_settings_store = EntityStore(self.db, UserSystemSettings)
        self._user_dict = {p.key: p.value for p in self.user_settings_store}

        self.store = store
        self.klass = store.klass
        self.context = context
        self.config = config
        self.refresh()
예제 #4
0
 def __init__(self, name, newest=None, db=None):
     self.name = name
     self.db = db
     self.messages = EntityStore(db, Message)
     self.newest = newest is not None and newest or self.last() or -1
예제 #5
0
class Topic(object):
    """
    message topic
    """

    def __init__(self, name, newest=None, db=None):
        self.name = name
        self.db = db
        self.messages = EntityStore(db, Message)
        self.newest = newest is not None and newest or self.last() or -1

    def last(self):
        """get row_id of the last (newest) message in the topic"""
        if self.name:
            cmd = """
                select max(row_id) n
                from attributes
                where kind=%s and attribute="topic" and value=%s
                """
            rec = self.db(cmd, self.messages.kind, self.name)
        else:
            cmd = 'select max(row_id) n from attributes where kind=%s'
            rec = self.db(cmd, self.messages.kind)
        if type(rec) == long:
            return 0
        row_id = rec.first()[0]
        return row_id or 0

    def put(self, message):
        """put a message in the topic"""
        return self.messages.put(
                Message(
                    topic=self.name,
                    timestamp=now(),
                    node=platform.node(),
                    body=json.dumps(message),
                    )
                )

    def send(self, *messages):
        """send list of messages

            >>> messages = setup_test()
            >>> t = messages.get('test_topic')
            >>> t.send('hey!', 'you!')
            [1L, 2L]
            >>> t.peek()
            u'hey!'
            >>> t.peek()
            u'hey!'
        """
        return [self.put(message) for message in messages]

    def _peek(self, newest=None):
        top_one = newest is not None and newest or self.newest or 0
        db = self.db
        if self.last() > self.newest:
            if self.name:
                cmd = """
                    select min(row_id) as row_id
                    from attributes
                    where
                        kind=%s and attribute="topic" and
                        value=%s and row_id>%s
                    """
                rec = db(cmd, self.messages.kind, self.name, top_one)
            else:
                cmd = """
                    select min(row_id) as row_id
                    from attributes where kind=%s and row_id>%s
                    """
                rec = db(cmd, self.messages.kind, top_one)
            if type(rec) == long:
                row_id = 0
            else:
                row_id = rec.first()[0]
            if row_id:
                message = self.messages.get(row_id)
                if message:
                    return row_id, message.topic, json.loads(message.body)
        raise EmptyException

    def peek(self, newest=None):
        """
        return the next message but don't remove it

            >>> messages = setup_test()
            >>> t = messages.get('test_topic')
            >>> t.peek()
            >>> t.put('hey!')
            1L
            >>> t.put('you!')
            2L
            >>> t.peek()
            u'hey!'
            >>> t.peek()
            u'hey!'
        """
        try:
            return self._peek(newest)[2]
        except EmptyException:
            return None

    def _poll(self, newest=None):
        r = self._peek(newest)
        self.newest = r[0]
        return r

    def poll(self, newest=None):
        """
        peek at the next message and increment internal pointer

            >>> messages = setup_test()
            >>> t = messages.get('test_topic')
            >>> t.put('hey!')
            1L
            >>> t.put('you!')
            2L
            >>> t.newest
            -1
            >>> t.poll()
            u'hey!'
            >>> t.newest
            1L
            >>> t.poll()
            u'you!'

            >>> raised = False
            >>> try:
            ...     t.poll()
            ... except EmptyException:
            ...     raised = True
            >>> raised
            True

            >>> t.newest = -1
            >>> t.poll()
            u'hey!'
        """
        return self._poll(newest)[2]

    def _pop(self):
        r = self._peek()
        row_id = r[0]
        self.messages.delete(row_id)
        if self.messages.db.rowcount > 0:
            self.newest = row_id
            return r
        else:
            # If we were unable to delete it then soneone else
            # has already deleted it between the time that
            # we saw it and the time we attempted to delete it.
            raise EmptyException

    def pop(self):
        """
        read next message and remove it from the topic

            >>> messages = setup_test()
            >>> t = messages.get('test_topic')
            >>> t.put('hey!')
            1L
            >>> t.put('you!')
            2L
            >>> t.len()
            2L
            >>> t._peek()
            (1L, 'test_topic', u'hey!')
            >>> t.pop()
            u'hey!'
            >>> t.len()
            1L
            >>> t.pop()
            u'you!'
            >>> t.len()
            0L
            >>> t.pop()
            >>> t.newest = -1
            >>> raised = False
            >>> try:
            ...     t._pop()
            ... except EmptyException:
            ...     raised = True
            >>> raised
            True
        """
        try:
            return self._pop()[2]
        except EmptyException:
            return None

    def len(self, newest=None):
        """
        return the number of messages in the topic

            >>> messages = setup_test()
            >>> t = messages.get('test_topic')
            >>> t.put('hey!')
            1L
            >>> t.put('you!')
            2L
            >>> t.len()
            2L
        """
        if self.last() > self.newest:
            if self.name:
                cmd = """
                    select count(row_id) as n
                    from attributes
                    where kind=%s and attribute="topic" and
                    value=%s and row_id>%s
                    """
                t = self.db(cmd, self.messages.kind, self.name, self.newest)
            else:
                cmd = """select count(row_id) as n
                    from attributes
                    where kind=%s and row_id>%s
                    """
                t = self.db(cmd, self.messages.kind, self.newest)
            n = t.first()[0] or 0L
            return n
        return 0L

    def __len__(self):
        """
        return the number of messages in a topic as an int
        (note: for large number of messages use t.len()

            >>> messages = setup_test()
            >>> t = messages.get('test_topic')
            >>> t.put('hey!')
            1L
            >>> t.put('you!')
            2L
            >>> len(t)
            2
        """
        return self.len()

    def __iter__(self):
        """
        iterate through a topic

            >>> messages = setup_test()
            >>> t = messages.get('test_topic')
            >>> t.put('hey!')
            1L
            >>> t.put('you!')
            2L
            >>> for m in t: print m
            hey!
            you!
        """
        return TopicIterator(self, self.newest)

    def _wait(self, delay=DELAY, timeout=15):
        """
        wait for a message to arrive and return it in
        raw form

            >>> messages = setup_test()
            >>> t = messages.get('test_topic')
            >>> t.put('hey!')
            1L
            >>> t.put('you!')
            2L
            >>> t._wait()
            (1L, 'test_topic', u'hey!')
            >>> t._wait()
            (2L, 'test_topic', u'you!')
        """
        deadline = time.time() + timeout
        while True:
            try:
                msg = self._pop()
            except EmptyException:
                msg = None
            if msg:
                return msg
            time.sleep(delay)
            if time.time() > deadline:
                raise WaitException

    def wait(self, delay=DELAY, timeout=15):
        """
        wait for a message to arrive and return it

            >>> messages = setup_test()
            >>> t = messages.get('test_topic')
            >>> t.put('hey!')
            1L
            >>> t.put('you!')
            2L
            >>> t.wait()
            u'hey!'
            >>> t.wait()
            u'you!'
        """
        deadline = time.time() + timeout
        while True:
            msg = self.pop()
            if msg:
                return msg
            time.sleep(delay)
            if time.time() > deadline:
                raise WaitException

    def listen(self, f, delay=DELAY, meta=False):
        """
        observe but don't consume messages

            >>> messages = setup_test()
            >>> t = messages.get('test_topic')
            >>> t.put('hey!')
            1L
            >>> t.put('you!')
            2L
            >>> def echo(m):
            ...     print m
            ...     return m == 'you!'
            >>> t.listen(echo)
            hey!
            you!
            2L

            >>> t1 = messages.topic('test_topic1')
            >>> t2 = messages.topic('test_topic2')
            >>> t3 = messages.topic(None)

            >>> t1.put('hey!')
            3L
            >>> t2.put('you!')
            4L
            >>> def echo(m):
            ...     print m
            ...     return m == 'you!'
            >>> t3.listen(echo)
            hey!
            you!
            2L

        """
        n = 0L
        done = False
        while not done:
            try:
                more_to_do = True
                while more_to_do:
                    try:
                        p = self._poll()
                    except EmptyException:
                        more_to_do = False
                    else:
                        if meta:
                            done = f(p)
                        else:
                            done = f(p[2])
                        n += 1
            except StopListening:
                return n
            else:
                time.sleep(delay)
        return n

    def responder(self, job_id):
        response_topic = response_topic_name(self.name, job_id)
        return Topic(response_topic, 1, self.db)

    def respond(self, job_id, message):
        return self.responder(job_id).send(message)

    def join(self, jobs):
        """wait for responses from consumers"""
        return [
                Topic(
                    response_topic_name(self.name, job),
                    newest=job,
                    db=self.db,
                    ).wait() for job in jobs
                ]

    def call(self, *messages):
        """send messages and wait for responses"""
        return self.join(self.send(*messages))

    def handle(self, f, timeout=0, delay=DELAY, one_pass=False):
        """respond to and consume messages

            >>> messages = setup_test()
            >>> t = messages.get('test_topic')
            >>> def echo(m):
            ...     if m == 'quit': raise StopHandling
            ...     print 'got', repr(m)
            >>> t.put('hey!')
            1L
            >>> t.put('you!')
            2L
            >>> t.put('quit')
            3L
            >>> t.handle(echo)
            got u'hey!'
            got u'you!'
            2L
        """
        deadline = timeout and time.time() + timeout
        done = False
        n = 0L
        while not done:
            try:
                try:
                    more_to_do = True
                    while more_to_do:
                        try:
                            row, topic, message = self._pop()
                            result = f(message)
                            response_topic = response_topic_name(topic, row)
                            t = Topic(response_topic, None, self.db)
                            t.send(result)
                            deadline = timeout and time.time() + timeout
                            n += 1
                        except EmptyException:
                            more_to_do = False
                        time.sleep(0)
                except StopHandling:
                    done = True
                else:
                    time.sleep(delay)
            except KeyboardInterrupt:
                done = True
            if timeout and time.time() > deadline:
                done = True
        return n

    def process(self, f):
        """respond to and consume current messages

            >>> messages = setup_test()
            >>> t = messages.get('test_topic')
            >>> def echo(m):
            ...     if m == 'quit': raise StopProcessing
            ...     print 'got', repr(m)
            >>> t.put('hey!')
            1L
            >>> t.put('you!')
            2L
            >>> t.put('quit')
            3L
            >>> t.process(echo)
            got u'hey!'
            got u'you!'
            2L
            >>> t.process(echo)
            0L
        """
        n = 0L
        more_to_do = True
        while more_to_do:
            try:
                row, topic, message = self._pop()
                if message is None:
                    result = f()
                else:
                    result = f(message)
                response_topic = response_topic_name(topic, row)
                t = Topic(response_topic, None, self.db)
                t.put(result)
                n += 1
            except StopProcessing:
                more_to_do = False
            except EmptyException:
                more_to_do = False
            time.sleep(0)
        return n
예제 #6
0
 def __init__(self, name, newest=None, db=None):
     self.name = name
     self.db = db
     self.messages = EntityStore(db, Message)
     self.newest = newest != None and newest or self.last() or -1
예제 #7
0
class Topic(object):
    """
    message topic
    """
    def __init__(self, name, newest=None, db=None):
        self.name = name
        self.db = db
        self.messages = EntityStore(db, Message)
        self.newest = newest != None and newest or self.last() or -1

    def last(self):
        """get row_id of the last (newest) message in the topic"""
        if self.name:
            cmd = """
                select max(row_id) n 
                from attributes 
                where kind=%s and attribute="topic" and value=%s
                """
            rec = self.db(cmd, self.messages.kind, self.name)
        else:
            cmd = 'select max(row_id) n from attributes where kind=%s'
            rec = self.db(cmd, self.messages.kind)
        if type(rec) == long:
            return 0
        row_id = rec.first()[0]
        return row_id or 0

    def put(self, message):
        """put a message in the topic"""
        return self.messages.put(
            Message(
                topic=self.name,
                timestamp=now(),
                node=platform.node(),
                body=json.dumps(message),
            ))

    def send(self, *messages):
        """send list of messages

            >>> messages = setup_test()
            >>> t = messages.get('test_topic')
            >>> t.send('hey!', 'you!')
            [1L, 2L]
            >>> t.peek()
            u'hey!'
            >>> t.peek()
            u'hey!'
        """
        return [self.put(message) for message in messages]

    def _peek(self, newest=None):
        top_one = newest != None and newest or self.newest or 0
        db = self.db
        if self.last() > self.newest:
            if self.name:
                cmd = """
                    select min(row_id) as row_id 
                    from attributes 
                    where kind=%s and attribute="topic" and value=%s and row_id>%s
                    """
                rec = db(cmd, self.messages.kind, self.name, top_one)
            else:
                cmd = """
                    select min(row_id) as row_id 
                    from attributes where kind=%s and row_id>%s
                    """
                rec = db(cmd, self.messages.kind, top_one)
            if type(rec) == long:
                row_id = 0
            else:
                row_id = rec.first()[0]
            if row_id:
                message = self.messages.get(row_id)
                if message:
                    return row_id, message.topic, json.loads(message.body)
        raise EmptyException

    def peek(self, newest=None):
        """
        return the next message but don't remove it

            >>> messages = setup_test()
            >>> t = messages.get('test_topic')
            >>> t.peek()
            >>> t.put('hey!')
            1L
            >>> t.put('you!')
            2L
            >>> t.peek()
            u'hey!'
            >>> t.peek()
            u'hey!'
        """
        try:
            return self._peek(newest)[2]
        except EmptyException:
            return None

    def _poll(self, newest=None):
        r = self._peek(newest)
        self.newest = r[0]
        return r

    def poll(self, newest=None):
        """
        peek at the next message and increment internal pointer

            >>> messages = setup_test()
            >>> t = messages.get('test_topic')
            >>> t.put('hey!')
            1L
            >>> t.put('you!')
            2L
            >>> t.newest
            -1
            >>> t.poll()
            u'hey!'
            >>> t.newest
            1L
            >>> t.poll()
            u'you!'

            >>> raised = False
            >>> try:
            ...     t.poll()
            ... except EmptyException:
            ...     raised = True
            >>> raised
            True

            >>> t.newest = -1
            >>> t.poll()
            u'hey!'
        """
        return self._poll(newest)[2]

    def _pop(self):
        r = self._peek()
        row_id = r[0]
        self.messages.delete(row_id)
        if self.messages.db.rowcount > 0:
            self.newest = row_id
            return r
        else:
            # If we were unable to delete it then soneone else
            # has already deleted it between the time that
            # we saw it and the time we attempted to delete it.
            raise EmptyException

    def pop(self):
        """
        read next message and remove it from the topic

            >>> messages = setup_test()
            >>> t = messages.get('test_topic')
            >>> t.put('hey!')
            1L
            >>> t.put('you!')
            2L
            >>> t.len()
            2L
            >>> t._peek()
            (1L, 'test_topic', u'hey!')
            >>> t.pop()
            u'hey!'
            >>> t.len()
            1L
            >>> t.pop()
            u'you!'
            >>> t.len()
            0L
            >>> t.pop()
            >>> t.newest = -1
            >>> raised = False
            >>> try:
            ...     t._pop()
            ... except EmptyException:
            ...     raised = True
            >>> raised
            True
        """
        try:
            return self._pop()[2]
        except EmptyException:
            return None

    def len(self, newest=None):
        """
        return the number of messages in the topic

            >>> messages = setup_test()
            >>> t = messages.get('test_topic')
            >>> t.put('hey!')
            1L
            >>> t.put('you!')
            2L
            >>> t.len()
            2L
        """
        if self.last() > self.newest:
            if self.name:
                cmd = """
                    select count(row_id) as n
                    from attributes
                    where kind=%s and attribute="topic" and value=%s and row_id>%s
                    """
                t = self.db(cmd, self.messages.kind, self.name, self.newest)
            else:
                cmd = """select count(row_id) as n
                    from attributes
                    where kind=%s and row_id>%s
                    """
                t = self.db(cmd, self.messages.kind, self.newest)
            n = t.first()[0] or 0L
            return n
        return 0L

    def __len__(self):
        """
        return the number of messages in a topic as an int
        (note: for large number of messages use t.len()

            >>> messages = setup_test()
            >>> t = messages.get('test_topic')
            >>> t.put('hey!')
            1L
            >>> t.put('you!')
            2L
            >>> len(t)
            2
        """
        return self.len()

    def __iter__(self):
        """
        iterate through a topic

            >>> messages = setup_test()
            >>> t = messages.get('test_topic')
            >>> t.put('hey!')
            1L
            >>> t.put('you!')
            2L
            >>> for m in t: print m
            hey!
            you!
        """
        return TopicIterator(self, self.newest)

    def wait(self, delay=1, timeout=15):
        """
        wait for a message to arrive and return it

            >>> messages = setup_test()
            >>> t = messages.get('test_topic')
            >>> t.put('hey!')
            1L
            >>> t.put('you!')
            2L
            >>> t.wait()
            u'hey!'
            >>> t.wait()
            u'you!'
        """
        deadline = time.time() + timeout
        while True:
            msg = self.pop()
            if msg:
                return msg
            time.sleep(delay)
            if time.time() > deadline:
                raise WaitException

    def listen(self, f, delay=1, meta=False):
        """
        observe but don't consume messages

            >>> messages = setup_test()
            >>> t = messages.get('test_topic')
            >>> t.put('hey!')
            1L
            >>> t.put('you!')
            2L
            >>> def echo(m):
            ...     print m
            ...     return m == 'you!'
            >>> t.listen(echo)
            hey!
            you!
            2L

            >>> t1 = messages.topic('test_topic1')
            >>> t2 = messages.topic('test_topic2')
            >>> t3 = messages.topic(None)

            >>> t1.put('hey!')
            3L
            >>> t2.put('you!')
            4L
            >>> def echo(m):
            ...     print m
            ...     return m == 'you!'
            >>> t3.listen(echo)
            hey!
            you!
            2L

        """
        n = 0L
        done = False
        while not done:
            try:
                more_to_do = True
                while more_to_do:
                    try:
                        p = self._poll()
                    except EmptyException:
                        more_to_do = False
                    else:
                        if meta:
                            done = f(p)
                        else:
                            done = f(p[2])
                        n += 1
            except StopListening:
                return n
            else:
                time.sleep(delay)
        return n

    def join(self, jobs):
        """wait for responses from consumers"""
        return [
            Topic(
                response_topic_name(self.name, job),
                newest=job,
                db=self.db,
            ).wait() for job in jobs
        ]

    def call(self, *messages):
        """send messages and wait for responses"""
        return self.join(self.send(*messages))

    def handle(self, f, timeout=0, delay=1, one_pass=False):
        """respond to and consume messages

            >>> messages = setup_test()
            >>> t = messages.get('test_topic')
            >>> def echo(m):
            ...     if m == 'quit': raise StopHandling
            ...     print 'got', repr(m)
            >>> t.put('hey!')
            1L
            >>> t.put('you!')
            2L
            >>> t.put('quit')
            3L
            >>> t.handle(echo)
            got u'hey!'
            got u'you!'
            2L
        """
        deadline = timeout and time.time() + timeout
        done = False
        n = 0L
        while not done:
            try:
                try:
                    more_to_do = True
                    while more_to_do:
                        try:
                            row, topic, message = self._pop()
                            result = f(message)
                            t = Topic(response_topic_name(topic, row), None,
                                      self.db)
                            t.send(result)
                            deadline = timeout and time.time() + timeout
                            n += 1
                        except EmptyException:
                            more_to_do = False
                        time.sleep(0)
                except StopHandling:
                    done = True
                else:
                    time.sleep(delay)
            except KeyboardInterrupt:
                done = True
            if timeout and time.time() > deadline:
                done = True
        return n

    def process(self, f):
        """respond to and consume current messages

            >>> messages = setup_test()
            >>> t = messages.get('test_topic')
            >>> def echo(m):
            ...     if m == 'quit': raise StopProcessing
            ...     print 'got', repr(m)
            >>> t.put('hey!')
            1L
            >>> t.put('you!')
            2L
            >>> t.put('quit')
            3L
            >>> t.process(echo)
            got u'hey!'
            got u'you!'
            2L
            >>> t.process(echo)
            0L
        """
        n = 0L
        more_to_do = True
        while more_to_do:
            try:
                row, topic, message = self._pop()
                if message is None:
                    result = f()
                else:
                    result = f(message)
                response_topic = response_topic_name(topic, row)
                t = Topic(response_topic, None, self.db)
                t.put(result)
                n += 1
            except StopProcessing:
                more_to_do = False
            except EmptyException:
                more_to_do = False
            time.sleep(0)
        return n
예제 #8
0
 def __str__(self):
     return str(EntityStore(self.db, Message))
예제 #9
0
 def clear(self):
     return EntityStore(self.db, Message).zap()
예제 #10
0
 def app(self, app_name):
     """ return an app settings object from the site settings """
     from zoom import manager, EntityStore
     return Settings(EntityStore(self.store.db, ApplicationSettings),
                     manager.get_app(app_name), app_name)