Source code for memcachio.routing
from __future__ import annotations
import hashlib
from collections.abc import Callable
from .errors import NoAvailableNodes
from .types import SingleMemcachedInstanceEndpoint
def md5_hasher(key: str) -> int:
return int(hashlib.md5(key.encode("utf-8")).hexdigest(), 16)
[docs]
class KeyRouter:
def __init__(
self,
nodes: set[SingleMemcachedInstanceEndpoint] | None = None,
hasher: Callable[[str], int] | None = None,
) -> None:
"""
Rendezvous Hashing implementation to route keys to memcached
nodes.
:param nodes: set of memcached nodes that are candidates
:param hasher: function to use to hash a key to a node. If not
provided, a default implementation using :func:`hashlib.md5` from
the standard library will be used.
"""
self._hasher = hasher or md5_hasher
self.nodes: set[SingleMemcachedInstanceEndpoint] = nodes or set()
[docs]
def add_node(self, node: SingleMemcachedInstanceEndpoint) -> None:
"""
Add a node to the set of candidate nodes
"""
self.nodes.add(node)
[docs]
def remove_node(self, node: SingleMemcachedInstanceEndpoint) -> None:
"""
Remove a node from the set of candidate nodes
"""
self.nodes.discard(node)
[docs]
def get_node(self, key: str) -> SingleMemcachedInstanceEndpoint:
"""
Get the node associated with ``key``
"""
if not self.nodes:
raise NoAvailableNodes()
return max(self.nodes, key=lambda node: self._hasher(f"{node}:{key}"))