From abd36240e302c99b851a777c7d4bf2010e4ed982 Mon Sep 17 00:00:00 2001 From: Paul Harrison Date: Tue, 16 May 2023 19:20:58 +0100 Subject: [PATCH] feat: Add hand cache --- poetry.lock | 33 ++++++++++++++++++++++++++++++++- poker/cache.py | 38 ++++++++++++++++++++++++++++++++++++++ poker/settings.py | 14 ++++++++++++++ pyproject.toml | 1 + 4 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 poker/cache.py create mode 100644 poker/settings.py diff --git a/poetry.lock b/poetry.lock index 51f1c3c..e708b17 100644 --- a/poetry.lock +++ b/poetry.lock @@ -21,6 +21,18 @@ doc = ["packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"] test = ["contextlib2", "coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "mock (>=4)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (<0.15)", "uvloop (>=0.15)"] trio = ["trio (>=0.16,<0.22)"] +[[package]] +name = "async-timeout" +version = "4.0.2" +description = "Timeout context manager for asyncio programs" +category = "main" +optional = false +python-versions = ">=3.6" +files = [ + {file = "async-timeout-4.0.2.tar.gz", hash = "sha256:2163e1640ddb52b7a8c80d0a67a08587e5d245cc9c553a74a847056bc2976b15"}, + {file = "async_timeout-4.0.2-py3-none-any.whl", hash = "sha256:8ca1e4fcf50d07413d66d1a5e416e42cfdf5851c981d679a09851a6853383b3c"}, +] + [[package]] name = "attrs" version = "23.1.0" @@ -671,6 +683,25 @@ pluggy = ">=0.12,<2.0" [package.extras] testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"] +[[package]] +name = "redis" +version = "4.5.5" +description = "Python client for Redis database and key-value store" +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "redis-4.5.5-py3-none-any.whl", hash = "sha256:77929bc7f5dab9adf3acba2d3bb7d7658f1e0c2f1cafe7eb36434e751c471119"}, + {file = "redis-4.5.5.tar.gz", hash = "sha256:dc87a0bdef6c8bfe1ef1e1c40be7034390c2ae02d92dcd0c7ca1729443899880"}, +] + +[package.dependencies] +async-timeout = {version = ">=4.0.2", markers = "python_full_version <= \"3.11.2\""} + +[package.extras] +hiredis = ["hiredis (>=1.0.0)"] +ocsp = ["cryptography (>=36.0.1)", "pyopenssl (==20.0.1)", "requests (>=2.26.0)"] + [[package]] name = "rfc3986" version = "1.5.0" @@ -780,4 +811,4 @@ dev = ["black (>=19.3b0)", "pytest (>=4.6.2)"] [metadata] lock-version = "2.0" python-versions = ">=3.11,<3.12" -content-hash = "fb62fc026dc64b0f6707d666c39635b19459935e84947efdcbd7de5f68c70ff8" +content-hash = "31c2219942b27c557028971055b425a867f575c736c5c282593f712f1cc0fa77" diff --git a/poker/cache.py b/poker/cache.py new file mode 100644 index 0000000..3596412 --- /dev/null +++ b/poker/cache.py @@ -0,0 +1,38 @@ +from redis import Redis + +from poker.constants import Rank +from poker.models import Hand +from poker.settings import CacheSettings + + +def get_redis_connection(settings: CacheSettings | None = None) -> Redis: + """Get Redis connection.""" + if settings is None: + settings = CacheSettings() + return Redis.from_url(settings.url) + + +class Cache: + """Poker hands cache. + + TODO: Only cache sorted hands. + """ + + def __init__(self, conn: Redis | None = None) -> None: + """Initialize cache.""" + if conn is None: + self._conn = get_redis_connection() + else: + self._conn = conn + + def get_rank(self, hand: Hand) -> Rank | None: + """Get ranked hand from cache.""" + key = str(hand) + rank = self._conn.get(key) + if rank is None: + return None + return Rank(rank) + + def cache_rank(self, hand: Hand, rank: Rank) -> None: + """Cache ranked hand.""" + self._conn.set(str(hand), str(rank)) \ No newline at end of file diff --git a/poker/settings.py b/poker/settings.py new file mode 100644 index 0000000..409ef67 --- /dev/null +++ b/poker/settings.py @@ -0,0 +1,14 @@ +from pydantic import BaseSettings, RedisDsn + + +class CacheSettings(BaseSettings): + """Cache settings.""" + + url: RedisDsn + + class Config: + """Settings configuration.""" + + env_prefix = "cache_" + env_file = ".env" + env_file_encoding = "utf-8" diff --git a/pyproject.toml b/pyproject.toml index a81a73b..de389d5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,6 +11,7 @@ fastapi = "^0.87.0" loguru = "^0.6.0" pydantic = "^1.10.2" uvicorn = "^0.20.0" +redis = "^4.5.5" [tool.poetry.group.test.dependencies] coverage = "^6.5.0"