hashcounter
hashcounter is a tiny async Redis helper: per-string counter with a sliding TTL.
Input string → SHA-256 → key "{prefix}:{hash}" → atomic INCR + EXPIRE in one transaction.
Installation
pip install hashcounter
Requires redis>=5.0.0 and a running Redis server.
Quick start
import asyncio
from hashcounter import bump_string_counter
async def main() -> None:
count = await bump_string_counter(
"world_debug_test_v234",
redis_url="redis://localhost:6379/0",
key_prefix="llm7:seen",
ttl_seconds=600, # 10 minutes
)
print(count) # 1 on first call, then 2, 3, ...
if __name__ == "__main__":
asyncio.run(main())
FastAPI (shared Redis client)
from __future__ import annotations
import redis.asyncio as redis
from fastapi import FastAPI
from hashcounter import bump_string_counter
app = FastAPI()
r = redis.from_url("redis://localhost:6379/0", decode_responses=False)
@app.on_event("shutdown")
async def _shutdown() -> None:
await r.aclose()
@app.post("/hit")
async def hit(s: str) -> dict[str, int]:
count = await bump_string_counter(
s,
redis_url="redis://localhost:6379/0",
key_prefix="llm7:seen",
ttl_seconds=600,
client=r, # reuse connection pool
)
return {"count": count}
Behaviour
- Key:
f"{key_prefix}:{sha256(value)}". - Atomicity:
INCRandEXPIRErun in a singleMULTI/EXECtransaction. - Sliding TTL: TTL resets to
ttl_secondson every call. - First call: creates the key with value
1. - Return: current counter value (
int). - Validation: raises
ValueErrorifttl_seconds <= 0.
API
async def bump_string_counter(
value: str,
*,
redis_url: str,
key_prefix: str,
ttl_seconds: int = 600,
client: Optional[redis.Redis] = None,
) -> int:
"""Increment the counter and refresh TTL. Return the current value."""
Parameters:
value: arbitrary string to count.redis_url: Redis connection URL (ignored ifclientis provided).key_prefix: namespace prefix for keys.ttl_seconds: key time-to-live (seconds), refreshed on each call.client: existingredis.asyncio.Redisinstance (recommended in services).
Use cases
- Prompt/request deduplication and anti-spam windows.
- Per-key rate limiting by arbitrary features (prompt hash, user token, IP).
- Telemetry: “seen count in the last N minutes”.
Contributing
Issues and PRs are welcome: https://github.com/chigwell/hashcounter/issues.
License
Metadata
Release files for hashcounter 2025.8.241445
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| hashcounter-2025.8.241445.tar.gz | 4.5 kB | Without provenance | Details for hashcounter-2025.8.241445.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| hashcounter-2025.8.241445-py3-none-any.whl | Python 3 | none | any | Details for hashcounter-2025.8.241445-py3-none-any.whl |
Total release size: 9.2 kB
Release files / hashcounter-2025.8.241445.tar.gz
| Download URL | hashcounter-2025.8.241445.tar.gz |
|---|---|
| Size | 4.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
de6ffed20bfcf706b04830500ed3c39e47b5b82579dc4ad674ce84f4def18c38
|
|
BLAKE2b-256 checksum How to use checksums |
f0e7f89bf27dc8e8366038abd6def2ddad15487d89e1776d139f5dd68c8f65f1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/4.0.2 CPython/3.11.11
|
Release files / hashcounter-2025.8.241445-py3-none-any.whl
| Download URL | hashcounter-2025.8.241445-py3-none-any.whl |
|---|---|
| Size | 4.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d54136dabd124eaab7eb15b22241fcbf0aa77169a62781cf9bde3db8cbdd654b
|
|
BLAKE2b-256 checksum How to use checksums |
415ce03c23aa119d9f8a9b5246993d1932fbb4605bd3bdda7eb9025346cfbec3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/4.0.2 CPython/3.11.11
|
Security for hashcounter 2025.8.241445
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.