meta-memcache 1.1.2.dev5__tar.gz → 2.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {meta_memcache-1.1.2.dev5 → meta_memcache-2.0.0}/PKG-INFO +192 -23
- {meta_memcache-1.1.2.dev5 → meta_memcache-2.0.0}/README.md +189 -22
- {meta_memcache-1.1.2.dev5 → meta_memcache-2.0.0}/pyproject.toml +4 -3
- {meta_memcache-1.1.2.dev5 → meta_memcache-2.0.0}/src/meta_memcache/__init__.py +2 -3
- {meta_memcache-1.1.2.dev5 → meta_memcache-2.0.0}/src/meta_memcache/base/base_serializer.py +2 -1
- {meta_memcache-1.1.2.dev5 → meta_memcache-2.0.0}/src/meta_memcache/cache_client.py +4 -4
- {meta_memcache-1.1.2.dev5 → meta_memcache-2.0.0}/src/meta_memcache/commands/high_level_commands.py +138 -134
- {meta_memcache-1.1.2.dev5 → meta_memcache-2.0.0}/src/meta_memcache/commands/meta_commands.py +7 -29
- {meta_memcache-1.1.2.dev5 → meta_memcache-2.0.0}/src/meta_memcache/configuration.py +10 -10
- {meta_memcache-1.1.2.dev5 → meta_memcache-2.0.0}/src/meta_memcache/connection/memcache_socket.py +46 -89
- {meta_memcache-1.1.2.dev5 → meta_memcache-2.0.0}/src/meta_memcache/executors/default.py +48 -67
- {meta_memcache-1.1.2.dev5 → meta_memcache-2.0.0}/src/meta_memcache/extras/client_wrapper.py +7 -29
- {meta_memcache-1.1.2.dev5 → meta_memcache-2.0.0}/src/meta_memcache/extras/migrating_cache_client.py +12 -44
- {meta_memcache-1.1.2.dev5 → meta_memcache-2.0.0}/src/meta_memcache/extras/probabilistic_hot_cache.py +5 -4
- {meta_memcache-1.1.2.dev5 → meta_memcache-2.0.0}/src/meta_memcache/interfaces/executor.py +5 -10
- {meta_memcache-1.1.2.dev5 → meta_memcache-2.0.0}/src/meta_memcache/interfaces/meta_commands.py +7 -19
- {meta_memcache-1.1.2.dev5 → meta_memcache-2.0.0}/src/meta_memcache/interfaces/router.py +5 -10
- meta_memcache-2.0.0/src/meta_memcache/protocol.py +129 -0
- {meta_memcache-1.1.2.dev5 → meta_memcache-2.0.0}/src/meta_memcache/routers/default.py +5 -14
- {meta_memcache-1.1.2.dev5 → meta_memcache-2.0.0}/src/meta_memcache/routers/ephemeral.py +7 -17
- {meta_memcache-1.1.2.dev5 → meta_memcache-2.0.0}/src/meta_memcache/routers/gutter.py +7 -21
- meta_memcache-2.0.0/src/meta_memcache/routers/helpers.py +24 -0
- meta_memcache-2.0.0/src/meta_memcache/serializer.py +229 -0
- {meta_memcache-1.1.2.dev5 → meta_memcache-2.0.0}/src/meta_memcache/settings.py +4 -1
- meta_memcache-1.1.2.dev5/src/meta_memcache/protocol.py +0 -198
- meta_memcache-1.1.2.dev5/src/meta_memcache/routers/helpers.py +0 -23
- meta_memcache-1.1.2.dev5/src/meta_memcache/serializer.py +0 -55
- {meta_memcache-1.1.2.dev5 → meta_memcache-2.0.0}/LICENSE +0 -0
- {meta_memcache-1.1.2.dev5 → meta_memcache-2.0.0}/src/meta_memcache/base/__init__.py +0 -0
- {meta_memcache-1.1.2.dev5 → meta_memcache-2.0.0}/src/meta_memcache/base/base_cache_client.py +0 -0
- {meta_memcache-1.1.2.dev5 → meta_memcache-2.0.0}/src/meta_memcache/commands/__init__.py +0 -0
- {meta_memcache-1.1.2.dev5 → meta_memcache-2.0.0}/src/meta_memcache/connection/__init__.py +0 -0
- {meta_memcache-1.1.2.dev5 → meta_memcache-2.0.0}/src/meta_memcache/connection/pool.py +0 -0
- {meta_memcache-1.1.2.dev5 → meta_memcache-2.0.0}/src/meta_memcache/connection/providers.py +0 -0
- {meta_memcache-1.1.2.dev5 → meta_memcache-2.0.0}/src/meta_memcache/errors.py +0 -0
- {meta_memcache-1.1.2.dev5 → meta_memcache-2.0.0}/src/meta_memcache/events/__init__.py +0 -0
- {meta_memcache-1.1.2.dev5 → meta_memcache-2.0.0}/src/meta_memcache/events/write_failure_event.py +0 -0
- {meta_memcache-1.1.2.dev5 → meta_memcache-2.0.0}/src/meta_memcache/executors/__init__.py +0 -0
- {meta_memcache-1.1.2.dev5 → meta_memcache-2.0.0}/src/meta_memcache/extras/__init__.py +0 -0
- {meta_memcache-1.1.2.dev5 → meta_memcache-2.0.0}/src/meta_memcache/interfaces/__init__.py +0 -0
- {meta_memcache-1.1.2.dev5 → meta_memcache-2.0.0}/src/meta_memcache/interfaces/cache_api.py +0 -0
- {meta_memcache-1.1.2.dev5 → meta_memcache-2.0.0}/src/meta_memcache/interfaces/commands.py +0 -0
- {meta_memcache-1.1.2.dev5 → meta_memcache-2.0.0}/src/meta_memcache/interfaces/high_level_commands.py +0 -0
- {meta_memcache-1.1.2.dev5 → meta_memcache-2.0.0}/src/meta_memcache/metrics/__init__.py +0 -0
- {meta_memcache-1.1.2.dev5 → meta_memcache-2.0.0}/src/meta_memcache/metrics/base.py +0 -0
- {meta_memcache-1.1.2.dev5 → meta_memcache-2.0.0}/src/meta_memcache/metrics/prometheus.py +0 -0
- {meta_memcache-1.1.2.dev5 → meta_memcache-2.0.0}/src/meta_memcache/py.typed +0 -0
- {meta_memcache-1.1.2.dev5 → meta_memcache-2.0.0}/src/meta_memcache/routers/__init__.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: meta-memcache
|
|
3
|
-
Version:
|
|
3
|
+
Version: 2.0.0
|
|
4
4
|
Summary: Modern, pure python, memcache client with support for new meta commands.
|
|
5
5
|
Home-page: https://github.com/RevenueCat/meta-memcache-py
|
|
6
6
|
License: MIT
|
|
@@ -14,7 +14,9 @@ Classifier: Programming Language :: Python :: 3.9
|
|
|
14
14
|
Classifier: Programming Language :: Python :: 3.10
|
|
15
15
|
Classifier: Programming Language :: Python :: 3.11
|
|
16
16
|
Requires-Dist: marisa-trie (>=1.0.0,<2.0.0)
|
|
17
|
+
Requires-Dist: meta-memcache-socket (==0.1.3)
|
|
17
18
|
Requires-Dist: uhashring (>=2.1,<3.0)
|
|
19
|
+
Requires-Dist: zstandard (>=0.22.0,<0.23.0)
|
|
18
20
|
Project-URL: Repository, https://github.com/RevenueCat/meta-memcache-py
|
|
19
21
|
Description-Content-Type: text/markdown
|
|
20
22
|
|
|
@@ -117,14 +119,26 @@ will be gone or present, since they are stored in the same server). Note this is
|
|
|
117
119
|
also risky, if you place all keys of a user in the same server, and the server
|
|
118
120
|
goes down, the user life will be miserable.
|
|
119
121
|
|
|
120
|
-
###
|
|
121
|
-
|
|
122
|
+
### Custom domains:
|
|
123
|
+
You can add a domain to keys. This domain can be used for custom per-domain
|
|
124
|
+
metrics like hit ratios or to control serialization of the values.
|
|
125
|
+
```python:
|
|
126
|
+
Key("key:1:2", domain="example")
|
|
127
|
+
```
|
|
128
|
+
For example the ZstdSerializer allows to configure different dictionaries by
|
|
129
|
+
domain, so you can compress more efficiently data of different domains.
|
|
130
|
+
|
|
131
|
+
### Unicode/binary keys:
|
|
132
|
+
Both unicode and binary keys are supported, the keys will be hashed/encoded according to Meta commands
|
|
122
133
|
[binary encoded keys](https://github.com/memcached/memcached/wiki/MetaCommands#binary-encoded-keys)
|
|
123
134
|
specification.
|
|
124
135
|
|
|
125
|
-
|
|
136
|
+
Using binary keys can have benefits, saving space in memory. While over the wire the key
|
|
137
|
+
is transmited b64 encoded, the memcache server will use the byte representation, so it will
|
|
138
|
+
not have the 1/4 overhead of b64 encoding.
|
|
139
|
+
|
|
126
140
|
```python:
|
|
127
|
-
Key("🍺"
|
|
141
|
+
Key("🍺")
|
|
128
142
|
```
|
|
129
143
|
|
|
130
144
|
### Large keys:
|
|
@@ -176,17 +190,15 @@ of flags, and features, but are very low level for general use.
|
|
|
176
190
|
def meta_multiget(
|
|
177
191
|
self,
|
|
178
192
|
keys: List[Key],
|
|
179
|
-
flags: Optional[
|
|
180
|
-
|
|
181
|
-
token_flags: Optional[Dict[TokenFlag, bytes]] = None,
|
|
193
|
+
flags: Optional[RequestFlags] = None,
|
|
194
|
+
failure_handling: FailureHandling = DEFAULT_FAILURE_HANDLING,
|
|
182
195
|
) -> Dict[Key, ReadResponse]:
|
|
183
196
|
|
|
184
197
|
def meta_get(
|
|
185
198
|
self,
|
|
186
199
|
key: Key,
|
|
187
|
-
flags: Optional[
|
|
188
|
-
|
|
189
|
-
token_flags: Optional[Dict[TokenFlag, bytes]] = None,
|
|
200
|
+
flags: Optional[RequestFlags] = None,
|
|
201
|
+
failure_handling: FailureHandling = DEFAULT_FAILURE_HANDLING,
|
|
190
202
|
) -> ReadResponse:
|
|
191
203
|
|
|
192
204
|
def meta_set(
|
|
@@ -194,29 +206,98 @@ of flags, and features, but are very low level for general use.
|
|
|
194
206
|
key: Key,
|
|
195
207
|
value: Any,
|
|
196
208
|
ttl: int,
|
|
197
|
-
flags: Optional[
|
|
198
|
-
|
|
199
|
-
token_flags: Optional[Dict[TokenFlag, bytes]] = None,
|
|
209
|
+
flags: Optional[RequestFlags] = None,
|
|
210
|
+
failure_handling: FailureHandling = DEFAULT_FAILURE_HANDLING,
|
|
200
211
|
) -> WriteResponse:
|
|
201
212
|
|
|
202
213
|
def meta_delete(
|
|
203
214
|
self,
|
|
204
215
|
key: Key,
|
|
205
|
-
flags: Optional[
|
|
206
|
-
|
|
207
|
-
token_flags: Optional[Dict[TokenFlag, bytes]] = None,
|
|
216
|
+
flags: Optional[RequestFlags] = None,
|
|
217
|
+
failure_handling: FailureHandling = DEFAULT_FAILURE_HANDLING,
|
|
208
218
|
) -> WriteResponse:
|
|
209
219
|
|
|
210
220
|
def meta_arithmetic(
|
|
211
221
|
self,
|
|
212
222
|
key: Key,
|
|
213
|
-
flags: Optional[
|
|
214
|
-
|
|
215
|
-
token_flags: Optional[Dict[TokenFlag, bytes]] = None,
|
|
223
|
+
flags: Optional[RequestFlags] = None,
|
|
224
|
+
failure_handling: FailureHandling = DEFAULT_FAILURE_HANDLING,
|
|
216
225
|
) -> WriteResponse:
|
|
217
226
|
```
|
|
218
|
-
|
|
219
|
-
|
|
227
|
+
### Special arguments:
|
|
228
|
+
`RequestFlags` has the following arguments:
|
|
229
|
+
* `no_reply`: Set to True if the server should not send a response
|
|
230
|
+
* `return_client_flag`: Set to True if the server should return the client flag
|
|
231
|
+
* `return_cas_token`: Set to True if the server should return the CAS token
|
|
232
|
+
* `return_value`: Set to True if the server should return the value (Default)
|
|
233
|
+
* `return_ttl`: Set to True if the server should return the TTL
|
|
234
|
+
* `return_size`: Set to True if the server should return the size (useful if when paired with return_value=False, to get the size of the value)
|
|
235
|
+
* `return_last_access`: Set to True if the server should return the last access time
|
|
236
|
+
* `return_fetched`: Set to True if the server should return the fetched flag
|
|
237
|
+
* `return_key`: Set to True if the server should return the key in the response
|
|
238
|
+
* `no_update_lru`: Set to True if the server should not update the LRU on this access
|
|
239
|
+
* `mark_stale`: Set to True if the server should mark the value as stale
|
|
240
|
+
* `cache_ttl`: The TTL to set on the key
|
|
241
|
+
* `recache_ttl`: The TTL to use for recache policy
|
|
242
|
+
* `vivify_on_miss_ttl`: The TTL to use when vivifying a value on a miss
|
|
243
|
+
* `client_flag`: The client flag to store along the value (Useful to store value type, compression, etc)
|
|
244
|
+
* `ma_initial_value`: For arithmetic operations, the initial value to use (if the key does not exist)
|
|
245
|
+
* `ma_delta_value`: For arithmetic operations, the delta value to use
|
|
246
|
+
* `cas_token`: The CAS token to use when storing the value in the cache
|
|
247
|
+
* `opaque`: The opaque flag (will be echoed back in the response)
|
|
248
|
+
* `mode`: The mode to use when storing the value in the cache. See SET_MODE_* and MA_MODE_* constants
|
|
249
|
+
|
|
250
|
+
`FailureHandling` controls how the failures are handled. Has the arguments:
|
|
251
|
+
* `raise_on_server_error`: (`Optional[bool]`) Wether to raise on error:
|
|
252
|
+
- `True`: Raises on server errors
|
|
253
|
+
- `False`: Returns miss for reads and false on writes
|
|
254
|
+
- `None` (DEFAULT): Use the raise on error setting configured in the Router
|
|
255
|
+
* `track_write_failures``: (`bool`) Wether to track failures:
|
|
256
|
+
- `True` (DEFAULT): Track write failures
|
|
257
|
+
- `False`: Do not notify write failures
|
|
258
|
+
|
|
259
|
+
The default settings are usually good, but there are situations when you want control.
|
|
260
|
+
For example, a refill (populating an entry that was missing on cache) doesn't need to
|
|
261
|
+
track write failures. If fails to be written, the cache will still be empty, so no need
|
|
262
|
+
to track that as a write failure. Similarly sometimes you need to know if a write failed
|
|
263
|
+
due to CAS semantics, or because it was an add vs when it is due to server failure.
|
|
264
|
+
|
|
265
|
+
### Responses:
|
|
266
|
+
The responses are either:
|
|
267
|
+
* `ReadResponse`: `Union[Miss, Value, Success]`
|
|
268
|
+
* `WriteResponse`: `Union[Success, NotStored, Conflict, Miss]`
|
|
269
|
+
|
|
270
|
+
Which are:
|
|
271
|
+
* `Miss`: For key not found. No arguments
|
|
272
|
+
* `Success`: Successfull operation
|
|
273
|
+
- `flags`: `ResponseFlags`
|
|
274
|
+
* `Value`: For value responses
|
|
275
|
+
- `flags`: `ResponseFlags`
|
|
276
|
+
- `size`: `int` Size of the value
|
|
277
|
+
- `value`: `Any` The value
|
|
278
|
+
* `NotStored`: Not stored, for example "add" on exising key. No arguments.
|
|
279
|
+
* `Conflict`: Not stored, for example due to CAS mismatch. No arguments.
|
|
280
|
+
|
|
281
|
+
The `ResponseFlags` contains the all the returned flags. This metadata gives a lot of
|
|
282
|
+
control and posibilities, it is the strength of the meta protocol:
|
|
283
|
+
* `cas_token`: Compare-And-Swap token (integer value) or `None` if not returned
|
|
284
|
+
* `fetched`:
|
|
285
|
+
- `True` if fetched since being set
|
|
286
|
+
- `False` if not fetched since being set
|
|
287
|
+
- `None` if the server did not return this flag info
|
|
288
|
+
* `last_access`: time in seconds since last access (integer value) or `None` if not returned
|
|
289
|
+
* `ttl`: time in seconds until the value expires (integer value) or `None` if not returned
|
|
290
|
+
- The special value `-1` represents if the key will never expire
|
|
291
|
+
* `client_flag`: integer value or `None` if not returned
|
|
292
|
+
* `win`:
|
|
293
|
+
- `True` if the client won the right to repopulate
|
|
294
|
+
- `False` if the client lost the right to repopulate
|
|
295
|
+
- `None` if the server did not return a win/lose flag
|
|
296
|
+
* `stale`: `True` if the value is stale, `False` otherwise
|
|
297
|
+
* `real_size`: integer value or `None` if not returned
|
|
298
|
+
* `opaque flag`: bytes value or `None` if not returned
|
|
299
|
+
|
|
300
|
+
NOTE: You shouldn't use this api directly, unless you are implementing some custom high-level
|
|
220
301
|
command. See below for the usual memcache api.
|
|
221
302
|
|
|
222
303
|
## High level commands:
|
|
@@ -241,6 +322,33 @@ Invalidation...
|
|
|
241
322
|
stale_policy: Optional[StalePolicy] = None,
|
|
242
323
|
set_mode: SetMode = SetMode.SET, # Other are ADD, REPLACE, APPEND...
|
|
243
324
|
) -> bool:
|
|
325
|
+
"""
|
|
326
|
+
Write a value using the specified `set_mode`
|
|
327
|
+
"""
|
|
328
|
+
|
|
329
|
+
def refill(
|
|
330
|
+
self: HighLevelCommandMixinWithMetaCommands,
|
|
331
|
+
key: Union[Key, str],
|
|
332
|
+
value: Any,
|
|
333
|
+
ttl: int,
|
|
334
|
+
no_reply: bool = False,
|
|
335
|
+
) -> bool:
|
|
336
|
+
"""
|
|
337
|
+
Try to refill a value.
|
|
338
|
+
|
|
339
|
+
Use this method when you got a cache miss, read from DB and
|
|
340
|
+
are trying to refill the value.
|
|
341
|
+
|
|
342
|
+
DO NOT USE to write new state.
|
|
343
|
+
|
|
344
|
+
It will:
|
|
345
|
+
* use "ADD" mode, so it will fail if the value is already
|
|
346
|
+
present in cache.
|
|
347
|
+
* It will also disable write failure tracking. The write
|
|
348
|
+
failure tracking is often used to invalidate keys that
|
|
349
|
+
fail to be written. Since this is not writting new state,
|
|
350
|
+
there is no need to track failures.
|
|
351
|
+
"""
|
|
244
352
|
|
|
245
353
|
def delete(
|
|
246
354
|
self,
|
|
@@ -249,6 +357,12 @@ Invalidation...
|
|
|
249
357
|
no_reply: bool = False,
|
|
250
358
|
stale_policy: Optional[StalePolicy] = None,
|
|
251
359
|
) -> bool:
|
|
360
|
+
"""
|
|
361
|
+
Returns True if the key existed and it was deleted.
|
|
362
|
+
If the key is not found in the cache it will return False. If
|
|
363
|
+
you just want to the key to be deleted not caring of whether
|
|
364
|
+
it exists or not, use invalidate() instead.
|
|
365
|
+
"""
|
|
252
366
|
|
|
253
367
|
def invalidate(
|
|
254
368
|
self,
|
|
@@ -257,6 +371,9 @@ Invalidation...
|
|
|
257
371
|
no_reply: bool = False,
|
|
258
372
|
stale_policy: Optional[StalePolicy] = None,
|
|
259
373
|
) -> bool:
|
|
374
|
+
"""
|
|
375
|
+
Returns true of the key deleted or it didn't exist anyway
|
|
376
|
+
"""
|
|
260
377
|
|
|
261
378
|
def touch(
|
|
262
379
|
self,
|
|
@@ -264,6 +381,9 @@ Invalidation...
|
|
|
264
381
|
ttl: int,
|
|
265
382
|
no_reply: bool = False,
|
|
266
383
|
) -> bool:
|
|
384
|
+
"""
|
|
385
|
+
Modify the TTL of a key without retrieving the value
|
|
386
|
+
"""
|
|
267
387
|
|
|
268
388
|
def get_or_lease(
|
|
269
389
|
self,
|
|
@@ -272,6 +392,13 @@ Invalidation...
|
|
|
272
392
|
touch_ttl: Optional[int] = None,
|
|
273
393
|
recache_policy: Optional[RecachePolicy] = None,
|
|
274
394
|
) -> Optional[Any]:
|
|
395
|
+
"""
|
|
396
|
+
Get a key. On miss try to get a lease.
|
|
397
|
+
|
|
398
|
+
Guarantees only one cache client will get the miss and
|
|
399
|
+
gets to repopulate cache, while the others are blocked
|
|
400
|
+
waiting (according to the settings in the LeasePolicy)
|
|
401
|
+
"""
|
|
275
402
|
|
|
276
403
|
def get_or_lease_cas(
|
|
277
404
|
self,
|
|
@@ -280,6 +407,10 @@ Invalidation...
|
|
|
280
407
|
touch_ttl: Optional[int] = None,
|
|
281
408
|
recache_policy: Optional[RecachePolicy] = None,
|
|
282
409
|
) -> Tuple[Optional[Any], Optional[int]]:
|
|
410
|
+
"""
|
|
411
|
+
Same as get_or_lease(), but also return the CAS token so
|
|
412
|
+
it can be used during writes and detect races
|
|
413
|
+
"""
|
|
283
414
|
|
|
284
415
|
def get(
|
|
285
416
|
self,
|
|
@@ -287,6 +418,9 @@ Invalidation...
|
|
|
287
418
|
touch_ttl: Optional[int] = None,
|
|
288
419
|
recache_policy: Optional[RecachePolicy] = None,
|
|
289
420
|
) -> Optional[Any]:
|
|
421
|
+
"""
|
|
422
|
+
Get a key
|
|
423
|
+
"""
|
|
290
424
|
|
|
291
425
|
def multi_get(
|
|
292
426
|
self,
|
|
@@ -294,6 +428,9 @@ Invalidation...
|
|
|
294
428
|
touch_ttl: Optional[int] = None,
|
|
295
429
|
recache_policy: Optional[RecachePolicy] = None,
|
|
296
430
|
) -> Dict[Key, Optional[Any]]:
|
|
431
|
+
"""
|
|
432
|
+
Get multiple keys at once
|
|
433
|
+
"""
|
|
297
434
|
|
|
298
435
|
def get_cas(
|
|
299
436
|
self,
|
|
@@ -301,6 +438,10 @@ Invalidation...
|
|
|
301
438
|
touch_ttl: Optional[int] = None,
|
|
302
439
|
recache_policy: Optional[RecachePolicy] = None,
|
|
303
440
|
) -> Tuple[Optional[Any], Optional[int]]:
|
|
441
|
+
"""
|
|
442
|
+
Same as get(), but also return the CAS token so
|
|
443
|
+
it can be used during writes and detect races
|
|
444
|
+
"""
|
|
304
445
|
|
|
305
446
|
def get_typed(
|
|
306
447
|
self,
|
|
@@ -310,6 +451,9 @@ Invalidation...
|
|
|
310
451
|
recache_policy: Optional[RecachePolicy] = None,
|
|
311
452
|
error_on_type_mismatch: bool = False,
|
|
312
453
|
) -> Optional[T]:
|
|
454
|
+
"""
|
|
455
|
+
Same as get(), but ensure the type matched the provided cls
|
|
456
|
+
"""
|
|
313
457
|
|
|
314
458
|
def get_cas_typed(
|
|
315
459
|
self,
|
|
@@ -319,6 +463,10 @@ Invalidation...
|
|
|
319
463
|
recache_policy: Optional[RecachePolicy] = None,
|
|
320
464
|
error_on_type_mismatch: bool = False,
|
|
321
465
|
) -> Tuple[Optional[T], Optional[int]]:
|
|
466
|
+
"""
|
|
467
|
+
Same as get_typed(), but also return the CAS token so
|
|
468
|
+
it can be used during writes and detect races
|
|
469
|
+
"""
|
|
322
470
|
|
|
323
471
|
def delta(
|
|
324
472
|
self,
|
|
@@ -328,6 +476,9 @@ Invalidation...
|
|
|
328
476
|
no_reply: bool = False,
|
|
329
477
|
cas_token: Optional[int] = None,
|
|
330
478
|
) -> bool:
|
|
479
|
+
"""
|
|
480
|
+
Increment/Decrement a key that contains a counter
|
|
481
|
+
"""
|
|
331
482
|
|
|
332
483
|
def delta_initialize(
|
|
333
484
|
self,
|
|
@@ -339,6 +490,11 @@ Invalidation...
|
|
|
339
490
|
no_reply: bool = False,
|
|
340
491
|
cas_token: Optional[int] = None,
|
|
341
492
|
) -> bool:
|
|
493
|
+
"""
|
|
494
|
+
Increment/Decrement a key that contains a counter,
|
|
495
|
+
creating and setting it to the initial value if the
|
|
496
|
+
counter does not exist.
|
|
497
|
+
"""
|
|
342
498
|
|
|
343
499
|
def delta_and_get(
|
|
344
500
|
self,
|
|
@@ -347,6 +503,9 @@ Invalidation...
|
|
|
347
503
|
refresh_ttl: Optional[int] = None,
|
|
348
504
|
cas_token: Optional[int] = None,
|
|
349
505
|
) -> Optional[int]:
|
|
506
|
+
"""
|
|
507
|
+
Same as delta(), but return the resulting value
|
|
508
|
+
"""
|
|
350
509
|
|
|
351
510
|
def delta_initialize_and_get(
|
|
352
511
|
self,
|
|
@@ -357,9 +516,19 @@ Invalidation...
|
|
|
357
516
|
refresh_ttl: Optional[int] = None,
|
|
358
517
|
cas_token: Optional[int] = None,
|
|
359
518
|
) -> Optional[int]:
|
|
519
|
+
"""
|
|
520
|
+
Same as delta_initialize(), but return the resulting value
|
|
521
|
+
"""
|
|
360
522
|
```
|
|
361
523
|
|
|
362
|
-
#
|
|
524
|
+
# Reliability, consistency and best practices
|
|
525
|
+
We have published a deep-dive into some of the techniques to keep
|
|
526
|
+
cache consistent and reliable under high load that RevenueCat uses,
|
|
527
|
+
available thanks to this cache client.
|
|
528
|
+
|
|
529
|
+
See: https://www.revenuecat.com/blog/engineering/data-caching-revenuecat/
|
|
530
|
+
|
|
531
|
+
## Anti-dogpiling, preventing thundering herds:
|
|
363
532
|
Some commands receive `RecachePolicy`, `StalePolicy` and `LeasePolicy` for the
|
|
364
533
|
advanced anti-dogpiling control needed in high-qps environments:
|
|
365
534
|
|