Skip to content

Commit 60f1f5c

Browse files
committed
actually add file with implementation in
1 parent 0195167 commit 60f1f5c

File tree

1 file changed

+83
-0
lines changed

1 file changed

+83
-0
lines changed

src/zarr/storage/_latency.py

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
from __future__ import annotations
2+
3+
import asyncio
4+
5+
from zarr.storage._wrapper import WrapperStore
6+
from zarr.abc.store import ByteRequest, Store
7+
from zarr.core.buffer import Buffer, BufferPrototype
8+
9+
10+
class LatencyStore(WrapperStore[Store]):
11+
"""
12+
A wrapper class that takes any store class in its constructor and
13+
adds latency to the `set` and `get` methods. This can be used for
14+
performance testing.
15+
16+
Particularly useful for testing downstream applications which will
17+
interact with a high-latency zarr store implementation,
18+
such as one which read from or writes to remote object storage.
19+
For example, by using this class to wrap a ``MemoryStore`` instance,
20+
you can (crudely) simulate the latency of reading and writing from S3
21+
without having to actually use the network, or a mock like MinIO.
22+
23+
Parameters
24+
----------
25+
store : Store
26+
Store to wrap
27+
get_latency : float
28+
Amount of latency to add to each get call, in seconds. Default is 0.
29+
set_latency : float
30+
Amount of latency to add to each set call, in seconds. Default is 0.
31+
"""
32+
33+
get_latency: float
34+
set_latency: float
35+
36+
def __init__(self, cls: Store, *, get_latency: float = 0, set_latency: float = 0) -> None:
37+
self.get_latency = float(get_latency)
38+
self.set_latency = float(set_latency)
39+
self._store = cls
40+
41+
async def set(self, key: str, value: Buffer) -> None:
42+
"""
43+
Add latency to the ``set`` method.
44+
45+
Calls ``asyncio.sleep(self.set_latency)`` before invoking the wrapped ``set`` method.
46+
47+
Parameters
48+
----------
49+
key : str
50+
The key to set
51+
value : Buffer
52+
The value to set
53+
54+
Returns
55+
-------
56+
None
57+
"""
58+
await asyncio.sleep(self.set_latency)
59+
await self._store.set(key, value)
60+
61+
async def get(
62+
self, key: str, prototype: BufferPrototype, byte_range: ByteRequest | None = None
63+
) -> Buffer | None:
64+
"""
65+
Add latency to the ``get`` method.
66+
67+
Calls ``asyncio.sleep(self.get_latency)`` before invoking the wrapped ``get`` method.
68+
69+
Parameters
70+
----------
71+
key : str
72+
The key to get
73+
prototype : BufferPrototype
74+
The BufferPrototype to use.
75+
byte_range : ByteRequest, optional
76+
An optional byte range.
77+
78+
Returns
79+
-------
80+
buffer : Buffer or None
81+
"""
82+
await asyncio.sleep(self.get_latency)
83+
return await self._store.get(key, prototype=prototype, byte_range=byte_range)

0 commit comments

Comments
 (0)