Example #1
0
    def lock_unlock_key():  # pragma: NO COVER
        lock = yield _cache.global_lock_for_write(key)
        cache_value = yield _cache.global_get(key)
        assert lock in cache_value

        yield _cache.global_unlock_for_write(key, lock)
        cache_value = yield _cache.global_get(key)
        assert lock not in cache_value
Example #2
0
def test_global_get_clear_cache_soon_with_error(_batch, _global_cache):
    """Regression test for #633

    https://github.com/googleapis/python-ndb/issues/633
    """

    class TransientError(Exception):
        pass

    batch = _batch.get_batch.return_value
    future = _future_result("hi mom!")
    batch.add.return_value = future
    _global_cache.return_value = mock.Mock(
        transient_errors=(TransientError),
        clear_cache_soon=True,
        strict_read=False,
        clear=mock.Mock(side_effect=TransientError("oops!"), spec=()),
        spec=("transient_errors", "clear_cache_soon", "clear", "strict_read"),
    )

    with warnings.catch_warnings(record=True) as logged:
        assert _cache.global_get(b"foo").result() is None
        assert len(logged) == 2

    _global_cache.return_value.clear.assert_called_once_with()
Example #3
0
def lookup(key, options):
    """Look up a Datastore entity.

    Gets an entity from Datastore, asynchronously. Checks the global cache,
    first, if appropriate. Uses batching.

    Args:
        key (~datastore.Key): The key for the entity to retrieve.
        options (_options.ReadOptions): The options for the request. For
            example, ``{"read_consistency": EVENTUAL}``.

    Returns:
        :class:`~tasklets.Future`: If not an exception, future's result will be
            either an entity protocol buffer or _NOT_FOUND.
    """
    context = context_module.get_context()
    use_datastore = context._use_datastore(key, options)
    if use_datastore and options.transaction:
        use_global_cache = False
    else:
        use_global_cache = context._use_global_cache(key, options)

    if not (use_global_cache or use_datastore):
        raise TypeError(
            "use_global_cache and use_datastore can't both be False")

    entity_pb = _NOT_FOUND
    key_locked = False

    if use_global_cache:
        cache_key = _cache.global_cache_key(key)
        result = yield _cache.global_get(cache_key)
        key_locked = _cache.is_locked_value(result)
        if not key_locked:
            if result is not None:
                entity_pb = entity_pb2.Entity()
                entity_pb.MergeFromString(result)

            elif use_datastore:
                yield _cache.global_lock(cache_key, read=True)
                yield _cache.global_watch(cache_key)

    if entity_pb is _NOT_FOUND and use_datastore:
        batch = _batch.get_batch(_LookupBatch, options)
        entity_pb = yield batch.add(key)

        # Do not cache misses
        if use_global_cache and not key_locked:
            if entity_pb is not _NOT_FOUND:
                expires = context._global_cache_timeout(key, options)
                serialized = entity_pb.SerializeToString()
                yield _cache.global_compare_and_swap(cache_key,
                                                     serialized,
                                                     expires=expires)
            else:
                yield _cache.global_unwatch(cache_key)

    raise tasklets.Return(entity_pb)
Example #4
0
def test_global_get_with_error_strict(_batch, _global_cache, sleep):
    class TransientError(Exception):
        pass

    sleep.return_value = future_result(None)
    batch = _batch.get_batch.return_value
    future = _future_exception(TransientError("oops"))
    batch.add.return_value = future
    _global_cache.return_value = mock.Mock(
        transient_errors=(TransientError,),
        strict_read=True,
        spec=("transient_errors", "strict_read"),
    )

    with pytest.raises(TransientError):
        _cache.global_get(b"foo").result()

    _batch.get_batch.assert_called_with(_cache._GlobalCacheGetBatch)
    batch.add.assert_called_with(b"foo")
Example #5
0
def test_global_get(_batch, _global_cache):
    batch = _batch.get_batch.return_value
    future = _future_result("hi mom!")
    batch.add.return_value = future
    _global_cache.return_value = mock.Mock(
        transient_errors=(),
        strict_read=False,
        spec=("transient_errors", "strict_read"),
    )

    assert _cache.global_get(b"foo").result() == "hi mom!"
    _batch.get_batch.assert_called_once_with(_cache._GlobalCacheGetBatch)
    batch.add.assert_called_once_with(b"foo")
Example #6
0
def test_global_get_clear_cache_soon(_batch, _global_cache):
    batch = _batch.get_batch.return_value
    future = _future_result("hi mom!")
    batch.add.return_value = future
    _global_cache.return_value = mock.Mock(
        transient_errors=(),
        clear_cache_soon=True,
        spec=("transient_errors", "clear_cache_soon", "clear"),
    )

    with warnings.catch_warnings(record=True) as logged:
        assert _cache.global_get(b"foo").result() == "hi mom!"
        assert len(logged) == 1

    _batch.get_batch.assert_called_once_with(_cache._GlobalCacheGetBatch)
    batch.add.assert_called_once_with(b"foo")
    _global_cache.return_value.clear.assert_called_once_with()
Example #7
0
def test_global_get_with_error_not_strict(_batch, _global_cache):
    class TransientError(Exception):
        pass

    batch = _batch.get_batch.return_value
    future = _future_exception(TransientError("oops"))
    batch.add.return_value = future
    _global_cache.return_value = mock.Mock(
        transient_errors=(TransientError,),
        strict_read=False,
        spec=("transient_errors", "strict_read"),
    )

    with warnings.catch_warnings(record=True) as logged:
        assert _cache.global_get(b"foo").result() is None
        assert len(logged) == 1

    _batch.get_batch.assert_called_once_with(_cache._GlobalCacheGetBatch)
    batch.add.assert_called_once_with(b"foo")
Example #8
0
def test_global_get_with_error_strict_retry(_batch, _global_cache, sleep):
    class TransientError(Exception):
        pass

    sleep.return_value = future_result(None)
    batch = _batch.get_batch.return_value
    batch.add.side_effect = [
        _future_exception(TransientError("oops")),
        future_result("hi mom!"),
    ]
    _global_cache.return_value = mock.Mock(
        transient_errors=(TransientError,),
        strict_read=True,
        spec=("transient_errors", "strict_read"),
    )

    assert _cache.global_get(b"foo").result() == "hi mom!"
    _batch.get_batch.assert_called_with(_cache._GlobalCacheGetBatch)
    batch.add.assert_called_with(b"foo")
Example #9
0
def test_global_get(_batch):
    batch = _batch.get_batch.return_value
    assert _cache.global_get(b"foo") is batch.add.return_value
    _batch.get_batch.assert_called_once_with(_cache._GlobalCacheGetBatch)
    batch.add.assert_called_once_with(b"foo")