Beispiel #1
0
 def __init__(self, conn=None, parent=None, protocol=None):
     Configurable.__init__(self)
     self._defaultconn = conn
     self._parent = parent
     self._lockconnmark = None
     if protocol:
         self._protocol = protocol
     else:
         if parent:
             self._protocol = parent._protocol
         else:
             self._protocol = Redis()
Beispiel #2
0
 def __init__(self, conn = None, parent = None, protocol = None):
     Configurable.__init__(self)
     self._defaultconn = conn
     self._parent = parent
     self._lockconnmark = None
     if protocol:
         self._protocol = protocol
     else:
         if parent:
             self._protocol = parent._protocol
         else:
             self._protocol = Redis()
Beispiel #3
0
class RedisClientBase(Configurable):
    '''
    Connect to Redis server
    '''
    # Default connection URL for Redis client
    _default_url = 'tcp://localhost/'
    # Wait for the connection setup before raise an exception
    _default_timeout = 10
    # Select database
    _default_db = 0

    def __init__(self, conn=None, parent=None, protocol=None):
        Configurable.__init__(self)
        self._defaultconn = conn
        self._parent = parent
        self._lockconnmark = None
        if protocol:
            self._protocol = protocol
        else:
            if parent:
                self._protocol = parent._protocol
            else:
                self._protocol = Redis()

    def _get_connection(self, container, connection):
        if not connection.connected:
            for m in container.waitWithTimeout(
                    self.timeout,
                    self._protocol.statematcher(
                        connection, RedisConnectionStateEvent.CONNECTION_UP,
                        False)):
                yield m
            if container.timeout:
                raise RedisConnectionDown('Disconnected from redis server')

    def _get_default_connection(self, container):
        if not self._defaultconn:
            raise RedisConnectionDown('Not connected to redis server')
        if self._lockconnmark is not None:
            if self._lockconnmark >= 0:
                if not self._defaultconn.connected or self._defaultconn.connmark != self._lockconnmark:
                    raise RedisConnectionRestarted(
                        'Disconnected from redis server; reconnected is not allowed in with scope'
                    )
                else:
                    return
        for m in self._get_connection(container, self._defaultconn):
            yield m
        if self._lockconnmark is not None and self._lockconnmark < 0:
            self._lockconnmark = self._defaultconn.connmark

    def _shutdown_conn(self, container, connection):
        if connection:
            if connection.connected:
                # Send quit
                try:
                    for m in self._protocol.send_command(
                            connection, container, 'QUIT'):
                        yield m
                    for m in container.waitWithTimeout(
                            1, self._protocol.statematcher(connection)):
                        yield m
                except Exception:
                    for m in connection.shutdown():
                        yield m
                else:
                    if container.timeout:
                        for m in connection.shutdown(True):
                            yield m
            else:
                for m in connection.shutdown():
                    yield m

    def shutdown(self, container):
        '''
        Shutdown all connections to Redis server
        '''
        c = self._defaultconn
        self._defaultconn = None
        for m in self._shutdown_conn(container, c):
            yield m

    def release(self, container):
        '''
        Release the connection, leave it to be reused later.
        '''
        if not self._parent:
            for m in self.shutdown(container):
                yield m
        else:
            for m in self._parent._release_conn(container, self._defaultconn):
                yield m

    @contextmanager
    def context(self, container, release=True, lockconn=True):
        '''
        Use with statement to manage the connection
        
        :params release: if True(default), release the connection when leaving with scope
        
        :params lockconn: if True(default), do not allow reconnect during with scope;
                execute commands on a disconnected connection raises Exceptions.
        '''
        try:
            if lockconn:
                if self._lockconnmark is None:
                    # Lock next connmark
                    self._lockconnmark = -1
                    locked = True
            yield self
        finally:
            if locked:
                self._lockconnmark = None
            self._lockconnmark = None
            if release:
                container.subroutine(self.release(container), False)

    @_conn
    def execute_command(self, container, *args):
        '''
        execute command on current connection
        '''
        for m in self._protocol.execute_command(self._defaultconn, container,
                                                *args):
            yield m

    @_conn
    def batch_execute(self, container, *cmds):
        '''
        execute a batch of commands on current connection in pipeline mode
        '''
        for m in self._protocol.batch_execute(self._defaultconn, container,
                                              *cmds):
            yield m

    def register_script(self, container, script):
        '''
        register a script to this connection.
        
        :returns: registered script. This is a tuple (sha1, script). Pass the tuple to
                  eval_registered, ensure_registerd as registerd_script parameter.
        '''
        if len(script) < 43:
            container.retvalue = (None, script)
        else:
            for m in self.execute_command(container, 'SCRIPT', 'LOAD', script):
                yield m
            container.retvalue = (container.retvalue, script)

    def eval_registered(self, container, registerd_script, *args):
        '''
        eval a registered script. If the script is not cached on the server, it is automatically cached. 
        '''
        if registerd_script[0]:
            try:
                for m in self.execute_command(container, 'EVALSHA',
                                              registerd_script[0], *args):
                    yield m
            except RedisReplyException as exc:
                if exc.subtype == 'NOSCRIPT':
                    for m in self.execute_command(container, 'EVAL',
                                                  registerd_script[1], *args):
                        yield m
                else:
                    raise
        else:
            for m in self.execute_command(container, 'EVAL',
                                          registerd_script[1], *args):
                yield m

    def ensure_registerd(self, container, *scripts):
        '''
        Ensure that these scripts are cached on the server. Important when using scripts with batch_execute.
        :param container: routine container.
        :param \*scripts: registered script tuples, return value of register_script 
        '''
        loading = dict((s[0], s[1]) for s in scripts if s[0])
        if loading:
            keys = list(loading.keys())
            for m in self.execute_command(container, 'SCRIPT', 'EXISTS',
                                          *keys):
                yield m
            r = container.retvalue
            cmds = [('SCRIPT', 'LOAD', s)
                    for s in (loading[keys[i]] for i in range(0, len(keys))
                              if not r[i])]
            if cmds:
                for m in self.batch_execute(container, cmds):
                    yield m
Beispiel #4
0
class RedisClientBase(Configurable):
    '''
    Connect to Redis server
    '''
    _default_url = 'tcp://localhost/'
    _default_timeout = 10
    _default_db = 0
    def __init__(self, conn = None, parent = None, protocol = None):
        Configurable.__init__(self)
        self._defaultconn = conn
        self._parent = parent
        self._lockconnmark = None
        if protocol:
            self._protocol = protocol
        else:
            if parent:
                self._protocol = parent._protocol
            else:
                self._protocol = Redis()
    def _get_connection(self, container, connection):
        if not connection.connected:
            for m in container.waitWithTimeout(self.timeout, self._protocol.statematcher(connection, RedisConnectionStateEvent.CONNECTION_UP, False)):
                yield m
            if container.timeout:
                raise RedisConnectionDown('Disconnected from redis server')        
    def _get_default_connection(self, container):
        if not self._defaultconn:
            raise RedisConnectionDown('Not connected to redis server')
        if self._lockconnmark is not None:
            if self._lockconnmark >= 0:
                if not self._defaultconn.connected or self._defaultconn.connmark != self._lockconnmark:
                    raise RedisConnectionRestarted('Disconnected from redis server; reconnected is not allowed in with scope')
                else:
                    return
        for m in self._get_connection(container, self._defaultconn):
            yield m
        if self._lockconnmark is not None and self._lockconnmark < 0:
            self._lockconnmark = self._defaultconn.connmark
    def _shutdown_conn(self, container, connection):
        if connection:
            if connection.connected:
                # Send quit
                try:
                    for m in self._protocol.send_command(connection, container, 'QUIT'):
                        yield m
                    for m in container.waitWithTimeout(1, self._protocol.statematcher(connection)):
                        yield m
                except Exception:
                    for m in connection.shutdown():
                        yield m
                else:
                    if container.timeout:
                        for m in connection.shutdown(True):
                            yield m
            else:
                for m in connection.shutdown():
                    yield m
    def shutdown(self, container):
        '''
        Shutdown all connections to Redis server
        '''
        c = self._defaultconn
        self._defaultconn = None
        for m in self._shutdown_conn(container, c):
            yield m
    def release(self, container):
        '''
        Release the connection, leave it to be reused later.
        '''
        if not self._parent:
            for m in self.shutdown(container):
                yield m
        else:
            for m in self._parent._release_conn(container, self._defaultconn):
                yield m
    @contextmanager
    def context(self, container, release = True, lockconn = True):
        '''
        Use with statement to manage the connection
        
        :params release: if True(default), release the connection when leaving with scope
        
        :params lockconn: if True(default), do not allow reconnect during with scope;
                execute commands on a disconnected connection raises Exceptions.
        '''
        try:
            if lockconn:
                if self._lockconnmark is None:
                    # Lock next connmark
                    self._lockconnmark = -1
                    locked = True
            yield self
        finally:
            if locked:
                self._lockconnmark = None
            self._lockconnmark = None
            if release:
                container.subroutine(self.release(container), False)
    @_conn
    def execute_command(self, container, *args):
        '''
        execute command on current connection
        '''
        for m in self._protocol.execute_command(self._defaultconn, container, *args):
            yield m
    @_conn
    def batch_execute(self, container, *cmds):
        '''
        execute a batch of commands on current connection in pipeline mode
        '''
        for m in self._protocol.batch_execute(self._defaultconn, container, *cmds):
            yield m
    def register_script(self, container, script):
        '''
        register a script to this connection.
        :returns: registered script. This is a tuple (sha1, script). Pass the tuple to
                eval_registered, ensure_registerd as registerd_script parameter.
        '''
        if len(script) < 43:
            container.retvalue = (None, script)
        else:
            for m in self.execute_command(container, 'SCRIPT', 'LOAD', script):
                yield m
            container.retvalue = (container.retvalue, script)
    def eval_registered(self, container, registerd_script, *args):
        '''
        eval a registered script. If the script is not cached on the server, it is automatically cached. 
        '''
        if registerd_script[0]:
            try:
                for m in self.execute_command(container, 'EVALSHA', registerd_script[0], *args):
                    yield m
            except RedisReplyException as exc:
                if exc.subtype == 'NOSCRIPT':
                    for m in self.execute_command(container, 'EVAL', registerd_script[1], *args):
                        yield m
                else:
                    raise
        else:
            for m in self.execute_command(container, 'EVAL', registerd_script[1], *args):
                yield m
    def ensure_registerd(self, container, *scripts):
        '''
        Ensure that these scripts are cached on the server. Important when using scripts with batch_execute.
        :param container: routine container.
        :param *scripts: registered script tuples, return value of register_script 
        '''
        loading = dict((s[0], s[1]) for s in scripts if s[0])
        if loading:
            keys = list(loading.keys())
            for m in self.execute_command(container, 'SCRIPT', 'EXISTS', *keys):
                yield m
            r = container.retvalue
            cmds = [('SCRIPT', 'LOAD', s) for s in (loading[keys[i]] for i in range(0, len(keys)) if not r[i])]
            if cmds:
                for m in self.batch_execute(container, cmds):
                    yield m