예제 #1
0
    async def test_should_return_current_value_on_first_call_after_update_time_reached_but_not_expiration_time(self):
        # given
        value = 0

        async def get_value(arg, kwarg=None):
            return value

        get_value_cached = memoize(
            method=get_value,
            configuration=MutableCacheConfiguration
                .initialized_with(DefaultInMemoryCacheConfiguration())
                .set_entry_builder(ProvidedLifeSpanCacheEntryBuilder(update_after=timedelta(milliseconds=100),
                                                                     expire_after=timedelta(minutes=5)))
        )

        # when
        res1 = await get_value_cached('test', kwarg='args')
        time.sleep(.200)
        await _ensure_asyncio_background_tasks_finished()
        value = 1
        res2 = await get_value_cached('test', kwarg='args')

        # then
        self.assertEqual(0, res1)
        self.assertEqual(0, res2)
예제 #2
0
    def test_should_return_current_value_on_first_call_after_update_time_reached_but_not_expiration_time(
            self):
        # given
        value = 0

        @memoize(configuration=DefaultInMemoryCacheConfiguration(
            update_after=timedelta(milliseconds=100),
            expire_after=timedelta(minutes=5)))
        @gen.coroutine
        def get_value(arg, kwarg=None):
            return value

        # when
        res1 = yield get_value('test', kwarg='args')
        time.sleep(.200)
        yield _ensure_background_tasks_finished()
        value = 1
        # calling thrice be more confident about behaviour of parallel execution
        res2 = yield [
            get_value('test', kwarg='args'),
            get_value('test', kwarg='args'),
            get_value('test', kwarg='args'),
        ]

        # then
        self.assertEqual(0, res1)
        self.assertEqual([0, 0, 0], res2)
예제 #3
0
    def test_should_inform_eviction_strategy_on_entry_updated(self):
        # given
        key_extractor = Mock()
        key_extractor.format_key = Mock(return_value='key')

        eviction_strategy = Mock()

        @memoize(
            configuration=MutableCacheConfiguration
                .initialized_with(DefaultInMemoryCacheConfiguration())
                .set_entry_builder(ProvidedLifeSpanCacheEntryBuilder(update_after=timedelta(milliseconds=100)))
                .set_key_extractor(key_extractor)
                .set_eviction_strategy(eviction_strategy)
        )
        @gen.coroutine
        def sample_method(arg, kwarg=None):
            return arg, kwarg

        yield sample_method('test', kwarg='args')
        yield _ensure_background_tasks_finished()
        time.sleep(.200)
        eviction_strategy.mark_written.reset_mock()

        # when
        yield sample_method('test', kwarg='args')
        yield _ensure_background_tasks_finished()

        # then
        _assert_called_once_with(self, eviction_strategy.mark_written, ('key', AnyObject()), {})
예제 #4
0
    def test_should_release_keys_on_caching_multiple_elements(self):
        # given
        value = 0
        storage = LocalInMemoryCacheStorage()
        key_extractor = Mock()
        key_extractor.format_key = Mock(side_effect=lambda method, args, kwargs: str((args[0], kwargs.get('kwarg'))))

        @memoize(
            configuration=MutableCacheConfiguration
                .initialized_with(DefaultInMemoryCacheConfiguration())
                .set_eviction_strategy(LeastRecentlyUpdatedEvictionStrategy(capacity=2))
                .set_key_extractor(key_extractor)
                .set_storage(storage)
        )
        @gen.coroutine
        def get_value(arg, kwarg=None):
            return value

        # when
        yield get_value('test1', kwarg='args1')
        yield get_value('test2', kwarg='args2')
        yield get_value('test3', kwarg='args3')
        yield get_value('test4', kwarg='args4')
        yield _ensure_background_tasks_finished()

        # then
        s1 = yield storage.get("('test1', 'args1')")
        s2 = yield storage.get("('test2', 'args2')")
        s3 = yield storage.get("('test3', 'args3')")
        s4 = yield storage.get("('test4', 'args4')")

        self.assertIsNone(s1)
        self.assertIsNone(s2)
        self.assertIsNotNone(s3)
        self.assertIsNotNone(s4)
예제 #5
0
    def test_should_return_current_value_on_second_call_after_update_time_reached_but_not_expiration_time(self):
        # given
        value = 0

        @memoize(
            configuration=MutableCacheConfiguration
                .initialized_with(DefaultInMemoryCacheConfiguration())
                .set_entry_builder(ProvidedLifeSpanCacheEntryBuilder(update_after=timedelta(milliseconds=100),
                                                                     expire_after=timedelta(minutes=5)))
        )
        @gen.coroutine
        def get_value(arg, kwarg=None):
            return value

        # when
        res1 = yield get_value('test', kwarg='args')
        time.sleep(.200)
        yield _ensure_background_tasks_finished()
        value = 1
        yield get_value('test', kwarg='args')
        yield _ensure_background_tasks_finished()
        res2 = yield get_value('test', kwarg='args')

        # then
        self.assertEqual(0, res1)
        self.assertEqual(1, res2)
예제 #6
0
    async def test_should_return_same_value_on_constant_key_function(self):
        # given
        value = 0
        key_extractor = Mock()
        key_extractor.format_key = Mock(return_value='lol')

        async def get_value(arg, kwarg=None):
            return value

        get_value_cached = memoize(
            method=get_value,
            configuration=MutableCacheConfiguration
                .initialized_with(DefaultInMemoryCacheConfiguration())
                .set_key_extractor(key_extractor)
        )

        # when
        res1 = await get_value_cached('test1', kwarg='args1')
        time.sleep(.200)
        await _ensure_asyncio_background_tasks_finished()
        value = 1
        res2 = await get_value_cached('test2', kwarg='args2')

        # then
        self.assertEqual(0, res1)
        self.assertEqual(0, res2)
예제 #7
0
    def test_should_retrieve_entry_to_release_on_entry_added(self):
        # given
        key_extractor = Mock()
        key_extractor.format_key = Mock(side_effect=lambda method, args, kwargs: str((args, kwargs)))

        eviction_strategy = Mock()
        eviction_strategy.next_to_release = Mock(return_value='release-test')

        storage = Mock()
        storage.get = Mock(return_value=_as_future(None))
        storage.offer = Mock(return_value=_as_future(None))
        storage.release = Mock(return_value=_as_future(None))

        @memoize(
            configuration=MutableCacheConfiguration
                .initialized_with(DefaultInMemoryCacheConfiguration())
                .set_storage(storage)
                .set_key_extractor(key_extractor)
                .set_eviction_strategy(eviction_strategy)
        )
        @gen.coroutine
        def sample_method(arg, kwarg=None):
            return arg, kwarg

        # when
        yield sample_method('test', kwarg='args')
        yield _ensure_background_tasks_finished()

        # then
        eviction_strategy.next_to_release.assert_called_once_with()
        storage.release.assert_called_once_with('release-test')
예제 #8
0
    async def test_should_return_current_value_on_second_call_after_update_time_reached_but_not_expiration_time(self):
        # given
        value = 0

        async def get_value(arg, kwarg=None):
            return value

        get_value_cached = memoize(
            method=get_value,
            configuration=DefaultInMemoryCacheConfiguration(update_after=timedelta(milliseconds=100),
                                                            expire_after=timedelta(minutes=5)))

        # when
        res1 = await get_value_cached('test', kwarg='args')
        time.sleep(.200)
        await _ensure_asyncio_background_tasks_finished()
        value = 1
        await get_value_cached('test', kwarg='args')
        await _ensure_asyncio_background_tasks_finished()
        # calling thrice be more confident about behaviour of parallel execution
        res2 = await self._call_thrice(lambda: get_value_cached('test', kwarg='args'))

        # then
        self.assertEqual(0, res1)
        self.assertEqual([1, 1, 1], res2)
예제 #9
0
    def test_should_call_key_extractor_on_method_used(self):
        # given
        key_extractor = Mock()
        key_extractor.format_key = Mock(return_value='key')

        @memoize(configuration=MutableCacheConfiguration.initialized_with(
            DefaultInMemoryCacheConfiguration()).set_key_extractor(
                key_extractor))
        @gen.coroutine
        def sample_method(arg, kwarg=None):
            return arg, kwarg

        # when
        yield sample_method('test', kwarg='args')
        yield _ensure_background_tasks_finished()

        # then
        # ToDo: assert wrapped methods match somehow

        _assert_called_once_with(self, key_extractor.format_key, (
            AnyObject(),
            ('test', ),
            {
                'kwarg': 'args'
            },
        ), {})
예제 #10
0
    def test_should_return_same_value_on_constant_key_function(self):
        # given
        value = 0
        key_extractor = Mock()
        key_extractor.format_key = Mock(return_value='lol')

        @memoize(
            configuration=MutableCacheConfiguration
                .initialized_with(DefaultInMemoryCacheConfiguration())
                .set_key_extractor(key_extractor)
        )
        @gen.coroutine
        def get_value(arg, kwarg=None):
            return value

        # when
        res1 = yield get_value('test1', kwarg='args1')
        time.sleep(.200)
        yield _ensure_background_tasks_finished()
        value = 1
        res2 = yield get_value('test2', kwarg='args2')

        # then
        self.assertEqual(0, res1)
        self.assertEqual(0, res2)
예제 #11
0
    async def test_should_throw_exception_on_wrapped_method_failure(self):
        # given
        async def get_value(arg, kwarg=None):
            raise ValueError("Get lost")

        get_value_cached = memoize(method=get_value, configuration=DefaultInMemoryCacheConfiguration())

        # when
        with self.assertRaises(Exception) as context:
            await get_value_cached('test1', kwarg='args1')

        # then
        expected = CachedMethodFailedException('Refresh failed to complete', ValueError('Get lost', ))
        self.assertEqual(str(expected), str(context.exception))  # ToDo: consider better comparision
예제 #12
0
    async def test_should_throw_exception_on_configuration_not_ready(self):
        # given
        @memoize(configuration=MutableCacheConfiguration.initialized_with(
            DefaultInMemoryCacheConfiguration()).set_configured(False))
        async def get_value(arg, kwarg=None):
            raise ValueError("Get lost")

        # when
        with self.assertRaises(Exception) as context:
            await get_value('test1', kwarg='args1')

        # then
        expected = NotConfiguredCacheCalledException()
        self.assertEqual(str(expected), str(context.exception))
예제 #13
0
    async def test_should_throw_exception_on_refresh_timeout(self):
        # given
        async def get_value(arg, kwarg=None):
            await _ensure_asyncio_background_tasks_finished()
            time.sleep(.200)
            await _ensure_asyncio_background_tasks_finished()
            return 0

        get_value_cached = memoize(
            method=get_value,
            configuration=DefaultInMemoryCacheConfiguration(method_timeout=timedelta(milliseconds=100)))

        # when
        with self.assertRaises(Exception) as context:
            await get_value_cached('test1', kwarg='args1')

        # then
        expected = CachedMethodFailedException('Refresh timed out')
        self.assertEqual(str(expected), str(context.exception))  # ToDo: consider better comparision
예제 #14
0
    async def test_should_return_different_values_on_different_kwargs_with_default_key(self):
        # given
        value = 0

        async def get_value(arg, kwarg=None):
            return value

        get_value_cached = memoize(method=get_value, configuration=DefaultInMemoryCacheConfiguration())

        # when
        res1 = await get_value_cached('test', kwarg='args1')
        time.sleep(.200)
        await _ensure_asyncio_background_tasks_finished()
        value = 1
        res2 = await get_value_cached('test', kwarg='args2')

        # then
        self.assertEqual(0, res1)
        self.assertEqual(1, res2)
예제 #15
0
    async def test_should_return_cached_value_on_expiration_time_not_reached(
            self):
        # given
        value = 0

        @memoize(configuration=DefaultInMemoryCacheConfiguration(
            update_after=timedelta(minutes=1),
            expire_after=timedelta(minutes=2)))
        async def get_value(arg, kwarg=None):
            return value

        # when
        res1 = await get_value('test', kwarg='args')
        time.sleep(.200)
        await _ensure_asyncio_background_tasks_finished()
        value = 1
        # calling thrice be more confident about behaviour of parallel execution
        res2 = await self._call_thrice(lambda: get_value('test', kwarg='args'))

        # then
        self.assertEqual(0, res1)
        self.assertEqual([0, 0, 0], res2)
예제 #16
0
    def test_should_throw_exception_on_refresh_timeout(self):
        # given

        @memoize(
            configuration=MutableCacheConfiguration
                .initialized_with(DefaultInMemoryCacheConfiguration())
                .set_method_timeout(timedelta(milliseconds=100))
        )
        @gen.coroutine
        def get_value(arg, kwarg=None):
            yield _ensure_background_tasks_finished()
            time.sleep(.200)
            yield _ensure_background_tasks_finished()
            return 0

        # when
        with self.assertRaises(Exception) as context:
            yield get_value('test1', kwarg='args1')

        # then
        expected = CachedMethodFailedException('Refresh timed out')
        self.assertEqual(str(expected), str(context.exception))  # ToDo: consider better comparision
예제 #17
0
    def test_should_pass_extracted_key_to_storage_on_entry_added_to_cache(
            self):
        # given
        key_extractor = Mock()
        key_extractor.format_key = Mock(return_value='key')

        storage = Mock()
        storage.get = Mock(return_value=_as_future(None))
        storage.offer = Mock(return_value=_as_future(None))

        @memoize(configuration=MutableCacheConfiguration.initialized_with(
            DefaultInMemoryCacheConfiguration()).set_key_extractor(
                key_extractor).set_storage(storage))
        @gen.coroutine
        def sample_method(arg, kwarg=None):
            return arg, kwarg

        # when
        yield sample_method('test', kwarg='args')
        yield _ensure_background_tasks_finished()

        # then
        storage.get.assert_called_once_with('key')
        _assert_called_once_with(self, storage.offer, ('key', AnyObject()), {})
예제 #18
0
    async def test_complex_showcase(self):
        # given
        UPDATE_MS = 400.0
        UPDATE_S = UPDATE_MS / 1000
        EXPIRE_MS = 800.0
        EXPIRE_S = EXPIRE_MS / 1000

        @memoize(configuration=DefaultInMemoryCacheConfiguration(
            update_after=timedelta(milliseconds=UPDATE_MS),
            expire_after=timedelta(milliseconds=EXPIRE_MS)))
        async def get_value_or_throw(arg, kwarg=None):
            if should_throw:
                raise ValueError(value)
            else:
                return value

        # when #1: initial call
        value, should_throw = 'ok #1', False
        res1 = await get_value_or_throw('test', kwarg='args')

        # when #2: background refresh - returns stale
        time.sleep(UPDATE_S)
        await _ensure_asyncio_background_tasks_finished()
        value, should_throw = 'ok #2', False
        res2 = await get_value_or_throw('test', kwarg='args')

        # when #3: no refresh (cache up-to-date)
        time.sleep(.10)
        await _ensure_asyncio_background_tasks_finished()
        value, should_throw = 'ok #3', False
        res3 = await get_value_or_throw('test', kwarg='args')

        # when #4: no refresh (cache up-to-date) but starts throwing
        time.sleep(.10)
        await _ensure_asyncio_background_tasks_finished()
        value, should_throw = 'throws #1', True
        res4 = await get_value_or_throw('test', kwarg='args')

        # when #5: background refresh while throwing - returns stale
        time.sleep(UPDATE_S)
        await _ensure_asyncio_background_tasks_finished()
        value, should_throw = 'throws #2', True
        res5 = await get_value_or_throw('test', kwarg='args')

        # when #6: stale value from cache as method raised during background refresh at #5
        time.sleep(.10)
        await _ensure_asyncio_background_tasks_finished()
        value, should_throw = 'throws #3', True
        res6 = await get_value_or_throw('test', kwarg='args')

        # when #7: stale expired - cache throws synchronously
        time.sleep(EXPIRE_S)
        await _ensure_asyncio_background_tasks_finished()
        value, should_throw = 'throws #4', True
        with self.assertRaises(Exception) as context:
            await get_value_or_throw('test', kwarg='args')

        # then
        self.assertEqual('ok #1', res1)
        self.assertEqual('ok #1',
                         res2)  # previous value - refresh in background
        self.assertEqual('ok #2', res3)  # value from cache - still relevant
        self.assertEqual('ok #2', res4)  # value from cache - still relevant
        self.assertEqual('ok #2',
                         res5)  # stale from cache - refresh in background
        self.assertEqual(
            'ok #2',
            res6)  # stale from cache - should be updated but method throws
        expected = CachedMethodFailedException('Refresh failed to complete',
                                               ValueError('throws #4', ))
        self.assertEqual(str(expected), str(
            context.exception))  # ToDo: consider better comparision
예제 #19
0
from datetime import timedelta

from memoize.configuration import MutableCacheConfiguration, DefaultInMemoryCacheConfiguration
from memoize.entrybuilder import ProvidedLifeSpanCacheEntryBuilder
from memoize.eviction import LeastRecentlyUpdatedEvictionStrategy
from memoize.key import EncodedMethodNameAndArgsKeyExtractor
from memoize.storage import LocalInMemoryCacheStorage
from memoize.wrapper import memoize


@memoize(configuration=MutableCacheConfiguration
         .initialized_with(DefaultInMemoryCacheConfiguration())
         .set_method_timeout(value=timedelta(minutes=2))
         .set_entry_builder(ProvidedLifeSpanCacheEntryBuilder(update_after=timedelta(minutes=2),
                                                              expire_after=timedelta(minutes=5)))
         .set_eviction_strategy(LeastRecentlyUpdatedEvictionStrategy(capacity=2048))
         .set_key_extractor(EncodedMethodNameAndArgsKeyExtractor(skip_first_arg_as_self=False))
         .set_storage(LocalInMemoryCacheStorage())
         )
async def cached():
    return 'dummy'
예제 #20
0
from memoize.configuration import DefaultInMemoryCacheConfiguration
from memoize.wrapper import memoize


@memoize(configuration=DefaultInMemoryCacheConfiguration())
async def cached():
    return 'dummy'
예제 #21
0
from memoize.entrybuilder import ProvidedLifeSpanCacheEntryBuilder
from memoize.wrapper import memoize

# scenario configuration
concurrent_requests = 5
request_batches_execution_count = 50
cached_value_ttl_millis = 200
delay_between_request_batches_millis = 70

# results/statistics
unique_calls_under_memoize = 0
unique_calls_under_different_cache = 0


@memoize(configuration=MutableCacheConfiguration.initialized_with(
    DefaultInMemoryCacheConfiguration()).set_entry_builder(
        ProvidedLifeSpanCacheEntryBuilder(update_after=timedelta(
            milliseconds=cached_value_ttl_millis))))
async def cached_with_memoize():
    global unique_calls_under_memoize
    unique_calls_under_memoize += 1
    await asyncio.sleep(0.01)
    return unique_calls_under_memoize


@cached(ttl=cached_value_ttl_millis / 1000, cache=SimpleMemoryCache)
async def cached_with_different_cache():
    global unique_calls_under_different_cache
    unique_calls_under_different_cache += 1
    await asyncio.sleep(0.01)
    return unique_calls_under_different_cache
예제 #22
0
def memoize(method: Optional[Callable] = None,
            configuration: CacheConfiguration = None):
    """Wraps function with memoization.

    If entry reaches time it should be updated, refresh is performed in background,
    but current entry is still valid and may be returned.
    Once expiration time is reached, refresh is blocking and current entry is considered invalid.

    Note: If wrapped method times out after `method_timeout` (see configuration) the cache will not be populated 
    and a failure occurs.
    
    Note: If wrapped method throws an exception the cache will not be populated and failure occurs.
    
    Note: Failures are indicated by designated exceptions (not original ones).

    To force refreshing immediately upon call to a cached method, set 'force_refresh_memoized' keyword flag, so
    the method will block until it's cache is refreshed.

    Warning: Leaving default configuration is a bad idea as it may not fit your data (may cause OOMs 
    or cache for an inappropriate time).

    :param function method:                         function to be decorated
    :param CacheConfiguration configuration:        cache configuration; default: DefaultInMemoryCacheConfiguration

    :raises: CachedMethodFailedException            upon call: if cached method timed-out or thrown an exception
    :raises: NotConfiguredCacheCalledException      upon call: if provided configuration is not ready
    """

    if method is None:
        if configuration is None:
            configuration = DefaultInMemoryCacheConfiguration()
        return functools.partial(
            memoize,
            configuration=configuration,
        )

    logger = logging.getLogger('{}@{}'.format(memoize.__name__,
                                              method.__name__))
    logger.debug('wrapping %s with memoization - configuration: %s',
                 method.__name__, configuration)

    update_statuses = UpdateStatuses()

    async def try_release(key: CacheKey,
                          configuration_snapshot: CacheConfiguration) -> bool:
        if update_statuses.is_being_updated(key):
            return False
        try:
            await configuration_snapshot.storage().release(key)
            configuration_snapshot.eviction_strategy().mark_released(key)
            logger.debug('Released cache key %s', key)
            return True
        except Exception as e:
            logger.error('Failed to release cache key %s', key, e)
            return False

    async def refresh(actual_entry: Optional[CacheEntry], key: CacheKey,
                      value_future_provider: Callable[[], asyncio.Future],
                      configuration_snapshot: CacheConfiguration):
        if actual_entry is None and update_statuses.is_being_updated(key):
            logger.debug(
                'As entry expired, waiting for results of concurrent refresh %s',
                key)
            entry = await update_statuses.await_updated(key)
            if entry is None:
                raise CachedMethodFailedException(
                    'Concurrent refresh failed to complete')
            return entry
        elif actual_entry is not None and update_statuses.is_being_updated(
                key):
            logger.debug(
                'As update point reached but concurrent update already in progress, '
                'relying on concurrent refresh to finish %s', key)
            return actual_entry
        elif not update_statuses.is_being_updated(key):
            update_statuses.mark_being_updated(key)
            try:
                value_future = value_future_provider()
                value = await value_future
                offered_entry = configuration_snapshot.entry_builder().build(
                    key, value)
                await configuration_snapshot.storage().offer(
                    key, offered_entry)
                update_statuses.mark_updated(key, offered_entry)
                logger.debug('Successfully refreshed cache for key %s', key)

                eviction_strategy = configuration_snapshot.eviction_strategy()
                eviction_strategy.mark_written(key, offered_entry)
                to_release = eviction_strategy.next_to_release()
                if to_release is not None:
                    _call_soon(try_release, to_release, configuration_snapshot)

                return offered_entry
            except _timeout_error_type() as e:
                logger.debug('Timeout for %s: %s', key, e)
                update_statuses.mark_update_aborted(key)
                raise CachedMethodFailedException('Refresh timed out')
            except Exception as e:
                logger.debug('Error while refreshing cache for %s: %s', key, e)
                update_statuses.mark_update_aborted(key)
                raise CachedMethodFailedException('Refresh failed to complete',
                                                  e)

    @functools.wraps(method)
    async def wrapper(*args, **kwargs):
        if not configuration.configured():
            raise NotConfiguredCacheCalledException()

        configuration_snapshot = MutableCacheConfiguration.initialized_with(
            configuration)

        force_refresh = kwargs.pop('force_refresh_memoized', False)
        key = configuration_snapshot.key_extractor().format_key(
            method, args, kwargs)

        current_entry = await configuration_snapshot.storage().get(
            key)  # type: Optional[CacheEntry]
        if current_entry is not None:
            configuration_snapshot.eviction_strategy().mark_read(key)

        now = datetime.datetime.utcnow()

        def value_future_provider():
            return _apply_timeout(configuration_snapshot.method_timeout(),
                                  method(*args, **kwargs))

        if current_entry is None:
            logger.debug('Creating (blocking) entry for key %s', key)
            result = await refresh(current_entry, key, value_future_provider,
                                   configuration_snapshot)
        elif force_refresh:
            logger.debug('Forced entry update (blocking) for key %s', key)
            result = await refresh(current_entry, key, value_future_provider,
                                   configuration_snapshot)
        elif current_entry.expires_after <= now:
            logger.debug(
                'Entry expiration reached - entry update (blocking) for key %s',
                key)
            result = await refresh(current_entry, key, value_future_provider,
                                   configuration_snapshot)
        elif current_entry.update_after <= now:
            logger.debug(
                'Entry update point expired - entry update (async - current entry returned) for key %s',
                key)
            _call_soon(refresh, current_entry, key, value_future_provider,
                       configuration_snapshot)
            result = current_entry
        else:
            result = current_entry

        return result.value

    return wrapper
예제 #23
0
from memoize.configuration import DefaultInMemoryCacheConfiguration
from memoize.wrapper import memoize

# scenario configuration
concurrent_requests = 5
request_batches_execution_count = 50
cached_value_ttl_ms = 200
delay_between_request_batches_ms = 70

# results/statistics
unique_calls_under_memoize = 0
unique_calls_under_different_cache = 0


@memoize(configuration=DefaultInMemoryCacheConfiguration(
    update_after=timedelta(milliseconds=cached_value_ttl_ms)))
async def cached_with_memoize():
    global unique_calls_under_memoize
    unique_calls_under_memoize += 1
    await asyncio.sleep(0.01)
    return unique_calls_under_memoize


@cached(ttl=cached_value_ttl_ms / 1000, cache=SimpleMemoryCache)
async def cached_with_different_cache():
    global unique_calls_under_different_cache
    unique_calls_under_different_cache += 1
    await asyncio.sleep(0.01)
    return unique_calls_under_different_cache

예제 #24
0
from datetime import timedelta

from memoize.configuration import DefaultInMemoryCacheConfiguration
from memoize.wrapper import memoize


@memoize(configuration=DefaultInMemoryCacheConfiguration(
    capacity=4096,
    method_timeout=timedelta(minutes=2),
    update_after=timedelta(minutes=10),
    expire_after=timedelta(minutes=30)))
async def cached():
    return 'dummy'
예제 #25
0
            nom=nom,
            prenom="lala",
        )

    def get_tokens(self, code: str, redirect_uri: str) -> Tokens:
        return Tokens(access_token="dummy_access_token",
                      refresh_token="dummy_refresh_token")


# Ademe
# ------

from api.utils.endpoints import *


@memoize(configuration=DefaultInMemoryCacheConfiguration(
    update_after=timedelta(milliseconds=3000)))
async def get_authorization_header() -> dict:
    """Retrieve a service token to call ADEME users API"""
    token_parameters = {
        "client_id": AUTH_CLIENT_ID,
        "client_secret": AUTH_SECRET,
        "grant_type": "client_credentials",
    }
    token_response = requests.post(token_endpoint, data=token_parameters)

    if not token_response.ok:
        raise HTTPException(
            status_code=503,
            detail=f"{token_response.status_code} {token_endpoint}")

    token_json = token_response.json()