First Steps
The smallest grelmicro app is one pattern and one provider. The pattern carries no backend reference and finds the provider on its own.
Install
pip install "grelmicro[redis]"
See the installation guide for uv, poetry, and the other
backend extras.
Mental model
- Pattern: the object your app calls, such as
Lock("cart")orRateLimiter.sliding_window("api", ...). - Provider: owns a connection, such as
RedisProvider. - Component: wires a backend into the app, such as
CacheorCoordination. A Provider on its own registers one for every kind it serves, so you often name none. - Adapter: the concrete backend implementation. Providers usually hide it.
- Ambient binding:
micro.install(app)lets request and message handlers find the currentGrelmicroapp.
Your first app
Guard a shared resource with a distributed Lock. The provider says where the
lock state lives, so every worker takes the same lock.
from grelmicro import Grelmicro
from grelmicro.coordination import Lock
from grelmicro.providers.redis import RedisProvider
redis = RedisProvider("redis://localhost:6379/0")
micro = Grelmicro(uses=[redis])
lock = Lock("cart")
async def checkout() -> None:
async with lock:
...
async def main() -> None:
# The lock resolves its backend inside the app scope.
async with micro:
await checkout()
Start Redis with one command:
docker run -d -p 6379:6379 redis
Three things happen here:
Lock("cart")builds a lock namedcartwith default settings.RedisProvider(...)says where the shared state lives.Grelmicro(uses=[...])wires it into the app.
The lock carries no backend reference. It finds one when it is used, inside
async with micro:, which is why checkout() is called from there. In a web
app micro.install(app) extends that scope to your request handlers, so
handlers need no async with.
One caller holds cart at a time. The next caller waits for the release.
Construct a pattern
Every pattern is built the same way. Pass the name first, then tune with keyword arguments:
from grelmicro.coordination import Lock
lock = Lock("cart", lease_duration=60)
Patterns with variants use factory methods:
from grelmicro.resilience import RateLimiter
api = RateLimiter.sliding_window("api", limit=100, window=60)
Decorators take the same keyword arguments:
from grelmicro.cache import cached
@cached(ttl=30)
async def get_user(user_id: int) -> User:
...
Next
You built a pattern and wired it into an app. Next, wire it into a web
framework with micro.install(app).