Exemplo n.º 1
0
class InMemoryDataModelCache(DataModelCache):
    """ Implementation of the data model cache backed by an in-memory dictionary. """
    def __init__(self):
        self.cache = ExpiresDict()

    def retrieve(self, cache_key, loader, should_cache=is_not_none):
        not_found = [None]
        logger.debug('Checking cache for key %s', cache_key.key)
        result = self.cache.get(cache_key.key, default_value=not_found)
        if result != not_found:
            logger.debug('Found result in cache for key %s: %s', cache_key.key,
                         result)
            return json.loads(result)

        logger.debug('Found no result in cache for key %s; calling loader',
                     cache_key.key)
        result = loader()
        logger.debug('Got loaded result for key %s: %s', cache_key.key, result)
        if should_cache(result):
            logger.debug(
                'Caching loaded result for key %s with expiration %s: %s',
                cache_key.key, result, cache_key.expiration)
            expires = convert_to_timedelta(
                cache_key.expiration) + datetime.now()
            self.cache.set(cache_key.key, json.dumps(result), expires=expires)
            logger.debug(
                'Cached loaded result for key %s with expiration %s: %s',
                cache_key.key, result, cache_key.expiration)
        else:
            logger.debug('Not caching loaded result for key %s: %s',
                         cache_key.key, result)

        return result
Exemplo n.º 2
0
class MemoryOrchestrator(Orchestrator):
    def __init__(self, **kwargs):
        self.state = ExpiresDict()
        self.callbacks = {}

    def _callbacks_prefixed(self, key):
        return (callback for (prefix, callback) in self.callbacks.items() if key.startswith(prefix))

    def on_key_change(self, key, callback, restarter=None):
        self.callbacks[key] = callback

    def get_prefixed_keys(self, prefix):
        return {
            k: value for (k, value) in list(self.state.items())
            if k.startswith(prefix) and not k.endswith(REDIS_EXPIRED_SUFFIX) and not k.endswith(REDIS_EXPIRING_SUFFIX)
        }

    def get_key(self, key):
        return self.state[key]

    def set_key(self, key, value, overwrite=False, expiration=None):
        preexisting_key = key in self.state
        if preexisting_key and not overwrite:
            raise KeyError(key)

        # Simulate redis' behavior when using xx and the key does not exist.
        if not preexisting_key and overwrite:
            return

        absolute_expiration = None
        if expiration is not None:
            absolute_expiration = datetime.datetime.now() + datetime.timedelta(seconds=expiration)

        self.state.set(key, value, expires=absolute_expiration)
        self.state.set(slash_join(key, REDIS_EXPIRING_SUFFIX), value, expires=absolute_expiration)

        event = KeyEvent.CREATE if not preexisting_key else KeyEvent.SET
        for callback in self._callbacks_prefixed(key):
            callback(KeyChange(event, key, value))

    def delete_key(self, key):
        value = self.state[key]
        del self.state[key]

        for callback in self._callbacks_prefixed(key):
            callback(KeyChange(KeyEvent.DELETE, key, value))

    def lock(self, key, expiration=DEFAULT_LOCK_EXPIRATION):
        try:
            self.set_key(key, "", overwrite=False, expiration=expiration)
        except KeyError:
            return False
        return True            

    def shutdown(self):
        self.state = None
        self.callbacks = None
Exemplo n.º 3
0
class InMemoryDataModelCache(DataModelCache):
    """
    Implementation of the data model cache backed by an in-memory dictionary.
    """
    def __init__(self, cache_config):
        super(InMemoryDataModelCache, self).__init__(cache_config)
        self.cache = ExpiresDict()

    def empty_for_testing(self):
        self.cache = ExpiresDict()

    def retrieve(self, cache_key, loader, should_cache=is_not_none):
        not_found = [None]
        logger.debug("Checking cache for key %s", cache_key.key)
        result = self.cache.get(cache_key.key, default_value=not_found)
        if result != not_found:
            logger.debug("Found result in cache for key %s: %s", cache_key.key,
                         result)
            cache_count.labels("hit").inc()

            return json.loads(result)
        else:
            cache_count.labels("miss").inc()

        logger.debug("Found no result in cache for key %s; calling loader",
                     cache_key.key)
        result = loader()
        logger.debug("Got loaded result for key %s: %s", cache_key.key, result)
        if should_cache(result):
            logger.debug(
                "Caching loaded result for key %s with expiration %s: %s",
                cache_key.key,
                result,
                cache_key.expiration,
            )
            expires = convert_to_timedelta(
                cache_key.expiration) + datetime.now()
            self.cache.set(cache_key.key, json.dumps(result), expires=expires)
            logger.debug(
                "Cached loaded result for key %s with expiration %s: %s",
                cache_key.key,
                result,
                cache_key.expiration,
            )
        else:
            logger.debug("Not caching loaded result for key %s: %s",
                         cache_key.key, result)

        return result
Exemplo n.º 4
0
class MemoryOrchestrator(Orchestrator):
    def __init__(self, **kwargs):
        self.state = ExpiresDict()
        self.callbacks = {}

    def _callbacks_prefixed(self, prefix):
        return (callback for (key, callback) in iteritems(self.callbacks)
                if key.startswith(prefix))

    def on_key_change(self, key, callback, restarter=None):
        self.callbacks[key] = callback

    @coroutine
    def get_prefixed_keys(self, prefix):
        raise Return({
            k: value
            for (k, value) in self.state.items() if k.startswith(prefix)
        })

    @coroutine
    def get_key(self, key):
        raise Return(self.state[key])

    @coroutine
    def set_key(self, key, value, overwrite=False, expiration=None):
        preexisting_key = "key" in self.state
        if preexisting_key and not overwrite:
            raise KeyError

        absolute_expiration = None
        if expiration is not None:
            absolute_expiration = datetime.datetime.now() + datetime.timedelta(
                seconds=expiration)

        self.state.set(key, value, expires=absolute_expiration)

        event = KeyEvent.CREATE if not preexisting_key else KeyEvent.SET
        for callback in self._callbacks_prefixed(key):
            yield From(callback(KeyChange(event, key, value)))

    def set_key_sync(self, key, value, overwrite=False, expiration=None):
        """
    set_key, but without trollius coroutines.
    """
        preexisting_key = "key" in self.state
        if preexisting_key and not overwrite:
            raise KeyError

        absolute_expiration = None
        if expiration is not None:
            absolute_expiration = datetime.datetime.now() + datetime.timedelta(
                seconds=expiration)

        self.state.set(key, value, expires=absolute_expiration)

        event = KeyEvent.CREATE if not preexisting_key else KeyEvent.SET
        for callback in self._callbacks_prefixed(key):
            callback(KeyChange(event, key, value))

    @coroutine
    def delete_key(self, key):
        value = self.state[key]
        del self.state[key]

        for callback in self._callbacks_prefixed(key):
            yield From(callback(KeyChange(KeyEvent.DELETE, key, value)))

    @coroutine
    def lock(self, key, expiration=DEFAULT_LOCK_EXPIRATION):
        if key in self.state:
            raise Return(False)
        self.state.set(key, None, expires=expiration)
        raise Return(True)

    def shutdown(self):
        self.state = None
        self.callbacks = None