| 
 | 1 | +from __future__ import annotations  | 
 | 2 | + | 
 | 3 | +import asyncio  | 
1 | 4 | import pickle  | 
2 |  | -from typing import Any, Generic, TypeVar, cast  | 
 | 5 | +from typing import TYPE_CHECKING, Generic, TypeVar, cast  | 
 | 6 | + | 
 | 7 | +from zarr.storage.wrapper import WrapperStore  | 
 | 8 | + | 
 | 9 | +if TYPE_CHECKING:  | 
 | 10 | +    from typing import Any  | 
 | 11 | + | 
 | 12 | +    from zarr.abc.store import ByteRangeRequest  | 
 | 13 | +    from zarr.core.buffer.core import BufferPrototype  | 
3 | 14 | 
 
  | 
4 | 15 | import pytest  | 
5 | 16 | 
 
  | 
6 |  | -from zarr.abc.store import AccessMode, Store  | 
 | 17 | +from zarr.abc.store import AccessMode, ByteRangeRequest, Store  | 
7 | 18 | from zarr.core.buffer import Buffer, default_buffer_prototype  | 
8 | 19 | from zarr.core.common import AccessModeLiteral  | 
9 | 20 | from zarr.core.sync import _collect_aiterator  | 
@@ -352,3 +363,44 @@ async def test_set_if_not_exists(self, store: S) -> None:  | 
352 | 363 | 
 
  | 
353 | 364 |         result = await store.get("k2", default_buffer_prototype())  | 
354 | 365 |         assert result == new  | 
 | 366 | + | 
 | 367 | + | 
 | 368 | +class LatencyStore(WrapperStore[Store]):  | 
 | 369 | +    """  | 
 | 370 | +    A wrapper class that takes any store class in its constructor and  | 
 | 371 | +    adds latency to the `set` and `get` methods. This can be used for  | 
 | 372 | +    performance testing.  | 
 | 373 | +    """  | 
 | 374 | + | 
 | 375 | +    get_latency: float  | 
 | 376 | +    set_latency: float  | 
 | 377 | + | 
 | 378 | +    def __init__(self, cls: Store, *, get_latency: float = 0, set_latency: float = 0) -> None:  | 
 | 379 | +        self.get_latency = float(get_latency)  | 
 | 380 | +        self.set_latency = float(set_latency)  | 
 | 381 | +        self._wrapped = cls  | 
 | 382 | + | 
 | 383 | +    async def set(self, key: str, value: Buffer) -> None:  | 
 | 384 | +        await asyncio.sleep(self.set_latency)  | 
 | 385 | +        await self._wrapped.set(key, value)  | 
 | 386 | + | 
 | 387 | +    async def get(  | 
 | 388 | +        self, key: str, prototype: BufferPrototype, byte_range: ByteRangeRequest | None = None  | 
 | 389 | +    ) -> Buffer | None:  | 
 | 390 | +        """  | 
 | 391 | +        Add latency to the get method.  | 
 | 392 | +
  | 
 | 393 | +        Adds a sleep of `self.get_latency` seconds before calling the wrapped method.  | 
 | 394 | +
  | 
 | 395 | +        Parameters  | 
 | 396 | +        ----------  | 
 | 397 | +        key : str  | 
 | 398 | +        prototype : BufferPrototype  | 
 | 399 | +        byte_range : ByteRangeRequest, optional  | 
 | 400 | +
  | 
 | 401 | +        Returns  | 
 | 402 | +        -------  | 
 | 403 | +        buffer : Buffer or None  | 
 | 404 | +        """  | 
 | 405 | +        await asyncio.sleep(self.get_latency)  | 
 | 406 | +        return await self._wrapped.get(key, prototype=prototype, byte_range=byte_range)  | 
0 commit comments