Ejemplo n.º 1
0
class MemcachedAdapter(BaseAdapter):
    """
    Exposes a cache store using Memcached.

    Exposes `pymemcache`'s exceptions.
    """
    def __init__(self, host='localhost', port=11211, **kwargs):
        super().__init__()

        self.store = Client((host, port), **kwargs)

    def set(self, key, value, ttl):
        if ttl == -1:
            ttl = 0

        return self.store.set(key, value, expire=ttl)

    def batch_set(self, keys, values, ttls):
        # There's two reasons to recode pymemcache.set_multi():
        # - It returns a list of keys that failed to be inserted, and the base expects a boolean
        # - It only allows a unique ttl for all keys
        commands = []

        ttls = [0 if ttl == -1 else ttl for ttl in ttls]
        for key, value, ttl in zip(keys, values, ttls):
            ttl = self.store._check_integer(ttl, 'expire')  # pylint: disable=protected-access
            key = self.store.check_key(key)
            value, flags = self.store.serde.serialize(key, value)

            command = b'set ' + key
            command += b' ' + str(flags).encode(self.store.encoding)
            command += b' ' + ttl
            command += b' ' + str(len(value)).encode(
                self.store.encoding) + b'\r\n'
            command += value.encode(self.store.encoding) + b'\r\n'
            commands.append(command)

        results = self.store._misc_cmd(commands, 'set', False)  # pylint: disable=protected-access

        for line in results:
            if line == b'NOT_STORED':
                return False

        return True

    def get(self, key):
        value = self.store.get(key)

        return value

    def batch_get(self, keys):
        key_to_value = self.store.get_multi(keys)
        values = [
            key_to_value[key] if key in key_to_value else None for key in keys
        ]

        return values

    def delete(self, key):
        return self.store.delete(key, noreply=False)

    def batch_delete(self, keys):
        # Here as well, pymemcache.delete_multi() always returns True
        commands = []

        for key in keys:
            key = self.store.check_key(key)

            command = b'delete ' + key + b'\r\n'
            commands.append(command)

        results = self.store._misc_cmd(commands, 'delete', False)  # pylint: disable=protected-access

        for line in results:
            print(f"\"{line}\"")
            if line == b'NOT_FOUND':
                return False

        return True

    def exists(self, key):
        # Can't just cast to bool since we can store falsey values
        return self.store.get(key) is not None

    def flush(self):
        return self.store.flush_all(noreply=False)

    def ping(self):
        return bool(self.store.stats())

    @property
    def connection_exceptions(self):
        return (MemcacheUnexpectedCloseError, MemcacheServerError,
                MemcacheUnknownError)
Ejemplo n.º 2
0
class OCPyMemcacheClient(object):
    """
    OCPyMemcacheClient is the instrumented wrapper to provide
    traces and metrics to a pymemache.client.base.Client instance.
    It takes the exact arguments that a HashClient would take and
    underlyingly creates the client which it then wraps.
    The same usage pattern for the original client would apply here.
    """

    __TRACKING_OPERATION = TrackingOperation()

    def __init__(self, server_addr, *args, **kwargs):
        self.__pymc = PyMemcacheClient(server_addr, *args, **kwargs)

    def add(self, key, value, *args, **kwargs):
        return self.__TRACKING_OPERATION.trace_and_record_stats(
            'pymemcache.client.base.Client.add', self.__pymc.add, key, value,
            *args, **kwargs)

    def append(self, key, value, *args, **kwargs):
        return self.__TRACKING_OPERATION.trace_and_record_stats(
            'pymemcache.client.base.Client.append', self.__pymc.append, key,
            value, *args, **kwargs)

    def cas(self, key, value, cas, *args, **kwargs):
        return self.__TRACKING_OPERATION.trace_and_record_stats(
            'pymemcache.client.base.Client.cas', self.__pymc.cas, key, value,
            *args, **kwargs)

    def check_key(self, key):
        # Does not touch the remote end.
        return self.__pymc.check_key(key)

    def close(self):
        return self.__TRACKING_OPERATION.trace_and_record_stats(
            'pymemcache.client.base.Client.close', self.__pymc.close)

    def decr(self, key, value, *args, **kwargs):
        return self.__TRACKING_OPERATION.trace_and_record_stats(
            'pymemcache.client.base.Client.decr', self.__pymc.decr, key, value,
            *args, **kwargs)

    def delete(self, key, *args, **kwargs):
        return self.__TRACKING_OPERATION.trace_and_record_stats(
            'pymemcache.client.base.Client.delete', self.__pymc.delete, key,
            *args, **kwargs)

    def delete_many(self, keys, *args, **kwargs):
        return self.__TRACKING_OPERATION.trace_and_record_stats(
            'pymemcache.client.base.Client.delete_many',
            self.__pymc.delete_many, keys, *args, **kwargs)

    def delete_multi(self, keys, *args, **kwargs):
        return self.__TRACKING_OPERATION.trace_and_record_stats(
            'pymemcache.client.base.Client.delete_multi',
            self.__pymc.delete_multi, keys, *args, **kwargs)

    def flush_all(self, *args, **kwargs):
        return self.__TRACKING_OPERATION.trace_and_record_stats(
            'pymemcache.client.base.Client.flush_all', self.__pymc.flush_all,
            *args, **kwargs)

    def get(self, key, *args, **kwargs):
        return self.__TRACKING_OPERATION.trace_and_record_stats(
            'pymemcache.client.base.Client.get', self.__pymc.get, key, *args,
            **kwargs)

    def get_many(self, keys, *args, **kwargs):
        return self.__TRACKING_OPERATION.trace_and_record_stats(
            'pymemcache.client.base.Client.get_many', self.__pymc.get_many,
            key, *args, **kwargs)

    def get_multi(self, keys, *args, **kwargs):
        return self.__TRACKING_OPERATION.trace_and_record_stats(
            'pymemcache.client.base.Client.get_multi', self.__pymc.get_multi,
            key, *args, **kwargs)

    def gets(self, keys, *args, **kwargs):
        return self.__TRACKING_OPERATION.trace_and_record_stats(
            'pymemcache.client.base.Client.gets', self.__pymc.gets, keys,
            *args, **kwargs)

    def gets_many(self, keys, *args, **kwargs):
        return self.__TRACKING_OPERATION.trace_and_record_stats(
            'pymemcache.client.base.Client.gets_many', self.__pymc.gets_many,
            keys, *args, **kwargs)

    def incr(self, key, value, *args, **kwargs):
        return self.__TRACKING_OPERATION.trace_and_record_stats(
            'pymemcache.client.base.Client.incr', self.__pymc.incr, key, value,
            *args, **kwargs)

    def prepend(self, key, value, *args, **kwargs):
        return self.__TRACKING_OPERATION.trace_and_record_stats(
            'pymemcache.client.base.Client.prepend', self.__pymc.prepend, key,
            value, *args, **kwargs)

    def quit(self, *args, **kwargs):
        return self.__TRACKING_OPERATION.trace_and_record_stats(
            'pymemcache.client.base.Client.quit', self.__pymc.quit, *args,
            **kwargs)

    def replace(self, key, value, *args, **kwargs):
        return self.__TRACKING_OPERATION.trace_and_record_stats(
            'pymemcache.client.base.Client.replace', self.__pymc.replace, key,
            value, *args, **kwargs)

    def set(self, key, value, *args, **kwargs):
        return self.__TRACKING_OPERATION.trace_and_record_stats(
            'pymemcache.client.base.Client.set', self.__pymc.set, key, value,
            *args, **kwargs)

    def set_many(self, values, *args, **kwargs):
        return self.__TRACKING_OPERATION.trace_and_record_stats(
            'pymemcache.client.base.Client.set_many', self.__pymc.set_many,
            values, *args, **kwargs)

    def set_multi(self, values, *args, **kwargs):
        return self.__TRACKING_OPERATION.trace_and_record_stats(
            'pymemcache.client.base.Client.set_multi', self.__pymc.set_multi,
            values, *args, **kwargs)

    def stats(self, *args):
        return self.__TRACKING_OPERATION.trace_and_record_stats(
            'pymemcache.client.base.Client.stats', self.__pymc.stats, *args)

    def touch(self, key, *args, **kwargs):
        return self.__TRACKING_OPERATION.trace_and_record_stats(
            'pymemcache.client.base.Client.touch', self.__pymc.touch, *args,
            **kwargs)

    def version(self):
        return self.__TRACKING_OPERATION.trace_and_record_stats(
            'pymemcache.client.base.Client.version', self.__pymc.version)