Metadata-Version: 2.4
Name: openframe-adapters-db-redis
Version: 1.1.0
Summary: OpenFrame Microservice Suite - Redis key-value adapter.
Project-URL: Homepage, https://github.com/Furious-Meteors/openframe-adapters
Project-URL: Documentation, https://furious-meteors.github.io/openframe-adapters/
Project-URL: Repository, https://github.com/Furious-Meteors/openframe-adapters
Project-URL: Changelog, https://github.com/Furious-Meteors/openframe-adapters/blob/production/.github/CHANGELOG.md
Project-URL: Bug Tracker, https://github.com/Furious-Meteors/openframe-adapters/issues
Author-email: Furious Meteors Engineering <engineering@furiousmeteors.dev>
Maintainer-email: Furious Meteors Engineering <engineering@furiousmeteors.dev>
License: MIT
Keywords: cache,hexagonal,microservice,openframe,redis
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Database
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.11
Requires-Dist: openframe-core<3,>=2.0
Requires-Dist: redis[asyncio]>=5.0
Provides-Extra: dev
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest-mock>=3.14; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Description-Content-Type: text/markdown

# openframe-adapters-db-redis

Redis key-value adapter for the **OpenFrame Microservice Development Suite**.

Part of the [`openframe-adapters`](https://github.com/Furious-Meteors/openframe-adapters) monorepo.

---

## What it provides

| Symbol | Purpose |
|---|---|
| `RedisSettings` | Pydantic-settings subclass — reads all config from env vars |
| `RedisRepository[T]` | Generic async repository — `BaseRepository[T]` + `HealthCheck` |
| `get_redis_client()` | Async factory — creates and caches the `redis.asyncio.Redis` client |
| `RedisPlugin` | `OpenFramePlugin` — structured lifecycle via `PluginRegistry` |

## Installation

```bash
# Via meta-package (recommended)
pip install "openframe-adapters[redis]"

# Or directly
pip install openframe-adapters-db-redis
```

## Quick start

```python
from openframe.adapters.db.redis import RedisSettings, RedisRepository

settings = RedisSettings(redis_url="redis://localhost:6379/0")
repo = RedisRepository(settings)

# Store and retrieve
await repo.create({"id": "user-1", "name": "Alice"})
user = await repo.get("user-1")         # {"id": "user-1", "name": "Alice"}
await repo.update({"id": "user-1", "name": "Alice B."})
await repo.delete("user-1")             # True
```

## Configuration

| Env var | Default | Description |
|---|---|---|
| `REDIS_URL` | **required** | `redis://[:password@]host[:port][/db]` or `rediss://` for TLS |
| `REDIS_MAX_CONNECTIONS` | `10` | Max connections in pool |
| `REDIS_SOCKET_TIMEOUT` | `5.0` | Socket read/write timeout (seconds) |
| `REDIS_SOCKET_CONNECT_TIMEOUT` | `5.0` | Connection timeout (seconds) |
| `REDIS_KEY_PREFIX` | `"openframe"` | Key namespace — keys stored as `{prefix}:{id}` |
| `REDIS_DEFAULT_TTL` | `0` | TTL in seconds; `0` = no expiry |

## Typed domain objects

```python
from dataclasses import dataclass
from openframe.adapters.db.redis import RedisRepository, RedisSettings

@dataclass
class Session:
    id: str
    user_id: str
    token: str

class SessionRepository(RedisRepository[Session]):
    def _dict_to_entity(self, data: dict) -> Session:
        return Session(**data)
    def _entity_to_dict(self, entity: Session) -> dict:
        return {"id": entity.id, "user_id": entity.user_id, "token": entity.token}
```

## Plugin lifecycle (optional)

```python
from openframe.core.plugins import PluginRegistry
from openframe.adapters.db.redis import RedisPlugin, RedisSettings

registry = PluginRegistry()
registry.register(RedisPlugin(RedisSettings()))
await registry.initialize_all()

plugin = registry.get("cache")          # capability = "cache"
repo = plugin.get_repository()
```

## License

MIT — © Furious Meteors Engineering
