|
|
||
|---|---|---|
| src/redis_store | ||
| .gitignore | ||
| pyproject.toml | ||
| README.md | ||
redis
Async Redis wrapper over redis-py's asyncio client — a small, config-free, fail-loud
key/value + hash + ttl surface with a raw escape hatch for everything else. First of the
datastore trio (redis / psql / mysql), a sibling of the mongo lib.
Import name ≠ repo name. The repo/distribution is
redis, but you importredis_store— the driver package owns theredisimport namespace, so the lib can't also beredis. Install resolvesredis.git; code doesfrom redis_store import RedisDB.
Install
requirements.txt:
redis_store @ git+ssh://git@git.rethinkstudios.io/rethink-public/redis.git@v0.1.1
Direct:
pip install "redis_store @ git+ssh://git@git.rethinkstudios.io/rethink-public/redis.git@v0.1.1"
Pulls redis>=5 (redis-py, which ships the asyncio client — not the dead standalone
aioredis).
Drop the @v0.1.1 suffix from the line above to install the latest unpinned.
Usage
from redis_store import RedisDB
# construction is sync and opens no socket; connect() pings to fail loud on bad config
kv = await RedisDB(host="localhost", port=6379, db=0, password=None).connect()
await kv.set("user:1:name", "ada", ex=3600) # ex = ttl seconds (optional)
name = await kv.get("user:1:name") # "ada" (None if absent)
await kv.incr("hits") # atomic counter -> int
await kv.hset("user:1", mapping={"name": "ada", "role": "admin"})
role = await kv.hget("user:1", "role") # "admin"
everything = await kv.hgetall("user:1") # {"name": "ada", "role": "admin"}
await kv.close() # on shutdown
Context-manager form:
async with RedisDB(host="localhost") as kv:
await kv.incr("hits")
One client/pool per process — build it once, attach it to your app (app.kv = ...), share it.
Type contract
decode_responses=True by default: keys and string values come back as str (and
None for an absent key). Pass decode_responses=False at construction for raw bytes.
Counters and counts (incr/decr/exists/ttl) always return int regardless.
Error contract — fail loud
Unlike the mongo lib (which log-and-swallows, returning a safe default), this lib
re-raises. Every wrapped method catches the driver's RedisError, logs it via
logging.getLogger(__name__), and raises. A None / [] / {} return is only ever a
real result (absent key, empty hash) — never a swallowed failure. So a caller can trust
that no exception means the op succeeded.
For anything not wrapped — pipelines, pub/sub, scan, Lua, transactions — use the raw
escape hatch:
async with kv.client.pipeline() as pipe:
await pipe.set("a", 1).set("b", 2).execute()
kv.client is the underlying redis.asyncio.Redis: full driver surface, raises,
nothing swallowed.
Surface
- key/value:
get,set(optionalexttl),delete,exists,incr,decr - hash:
hget,hset(singlekey/valueormapping=),hgetall,hdel - expiry/ttl:
expire,ttl(driver sentinels pass through:-1no expiry,-2key absent) - raw:
clientproperty →redis.asyncio.Redis
Pub/sub and a pipeline() wrapper are intentionally not wrapped yet — the raw
client covers them; they'll be added when a consumer needs the ergonomics.
Versioning
Releases are tagged vX.Y.Z. The install line above pins a release; drop the @vX.Y.Z
suffix to install the latest unpinned. Pin deliberately for reproducible installs.