kiarina-lib-redis 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,39 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.so
5
+ *.egg-info/
6
+ dist/
7
+ build/
8
+ .ruff_cache/
9
+ .mypy_cache/
10
+ .pytest_cache/
11
+ .coverage
12
+ coverage.xml
13
+ htmlcov/
14
+
15
+ # uv
16
+ .uv_cache/
17
+
18
+ # Virtual environments & config
19
+ .venv/
20
+ .env
21
+
22
+ # IDE
23
+ .vscode/
24
+ *.code-workspace
25
+
26
+ # OS
27
+ .DS_Store
28
+
29
+ # Project specific
30
+ *.log
31
+ tmp/
32
+ ai.yaml
33
+
34
+ # Test data
35
+ tests/data/large/
36
+
37
+ # mise tasks (always include)
38
+ !mise-tasks/
39
+ !mise-tasks/**
@@ -0,0 +1 @@
1
+ 3.13
@@ -0,0 +1,26 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [1.0.0] - 2025-09-09
11
+
12
+ ### Added
13
+ - Initial release of kiarina-lib-redis
14
+ - Redis client with configuration management using pydantic-settings-manager
15
+ - Connection pooling and caching
16
+ - Retry mechanism for connection failures
17
+ - Support for both sync and async operations
18
+ - Type safety with full type hints and Pydantic validation
19
+ - Environment variable configuration support
20
+ - Runtime configuration overrides
21
+ - Multiple named configurations support
22
+
23
+ ### Dependencies
24
+ - redis>=6.4.0
25
+ - pydantic-settings>=2.10.1
26
+ - pydantic-settings-manager>=2.1.0
@@ -0,0 +1,280 @@
1
+ Metadata-Version: 2.4
2
+ Name: kiarina-lib-redis
3
+ Version: 1.0.0
4
+ Summary: Redis client library for kiarina namespace
5
+ Project-URL: Homepage, https://github.com/kiarina/kiarina-python
6
+ Project-URL: Repository, https://github.com/kiarina/kiarina-python
7
+ Project-URL: Issues, https://github.com/kiarina/kiarina-python/issues
8
+ Project-URL: Changelog, https://github.com/kiarina/kiarina-python/blob/main/packages/kiarina-lib-redis/CHANGELOG.md
9
+ Project-URL: Documentation, https://github.com/kiarina/kiarina-python/tree/main/packages/kiarina-lib-redis#readme
10
+ Author-email: kiarina <kiarinadawa@gmail.com>
11
+ Maintainer-email: kiarina <kiarinadawa@gmail.com>
12
+ License: MIT
13
+ Keywords: async,cache,client,database,pydantic,redis,settings
14
+ Classifier: Development Status :: 4 - Beta
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Operating System :: OS Independent
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Topic :: Database
22
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
23
+ Classifier: Typing :: Typed
24
+ Requires-Python: >=3.12
25
+ Requires-Dist: pydantic-settings-manager>=2.1.0
26
+ Requires-Dist: pydantic-settings>=2.10.1
27
+ Requires-Dist: redis>=6.4.0
28
+ Description-Content-Type: text/markdown
29
+
30
+ # kiarina-lib-redis
31
+
32
+ A Python client library for [Redis](https://redis.io/) with configuration management and connection pooling.
33
+
34
+ ## Features
35
+
36
+ - **Configuration Management**: Use `pydantic-settings-manager` for flexible configuration
37
+ - **Connection Pooling**: Automatic connection caching and reuse
38
+ - **Retry Support**: Built-in retry mechanism for connection failures
39
+ - **Sync & Async**: Support for both synchronous and asynchronous operations
40
+ - **Type Safety**: Full type hints and Pydantic validation
41
+
42
+ ## Installation
43
+
44
+ ```bash
45
+ pip install kiarina-lib-redis
46
+ ```
47
+
48
+ ## Quick Start
49
+
50
+ ### Basic Usage (Sync)
51
+
52
+ ```python
53
+ from kiarina.lib.redis import get_redis
54
+
55
+ # Get a Redis client with default settings
56
+ redis = get_redis()
57
+
58
+ # Basic operations
59
+ redis.set("key", "value")
60
+ value = redis.get("key")
61
+ print(value) # b'value'
62
+
63
+ # With decode_responses=True for string values
64
+ redis = get_redis(decode_responses=True)
65
+ redis.set("key", "value")
66
+ value = redis.get("key")
67
+ print(value) # 'value'
68
+ ```
69
+
70
+ ### Async Usage
71
+
72
+ ```python
73
+ from kiarina.lib.redis.asyncio import get_redis
74
+
75
+ async def main():
76
+ # Get an async Redis client
77
+ redis = get_redis(decode_responses=True)
78
+
79
+ # Basic operations
80
+ await redis.set("key", "value")
81
+ value = await redis.get("key")
82
+ print(value) # 'value'
83
+ ```
84
+
85
+ ## Configuration
86
+
87
+ This library uses [pydantic-settings-manager](https://github.com/kiarina/pydantic-settings-manager) for flexible configuration management.
88
+
89
+ ### Environment Variables
90
+
91
+ Configure the Redis connection using environment variables:
92
+
93
+ ```bash
94
+ # Redis connection URL
95
+ export KIARINA_LIB_REDIS_URL="redis://localhost:6379"
96
+
97
+ # Enable retry mechanism
98
+ export KIARINA_LIB_REDIS_USE_RETRY="true"
99
+
100
+ # Timeout settings
101
+ export KIARINA_LIB_REDIS_SOCKET_TIMEOUT="6.0"
102
+ export KIARINA_LIB_REDIS_SOCKET_CONNECT_TIMEOUT="3.0"
103
+
104
+ # Retry settings
105
+ export KIARINA_LIB_REDIS_RETRY_ATTEMPTS="3"
106
+ export KIARINA_LIB_REDIS_RETRY_DELAY="1.0"
107
+ ```
108
+
109
+ ### Programmatic Configuration
110
+
111
+ ```python
112
+ from kiarina.lib.redis import settings_manager
113
+
114
+ # Configure for multiple environments
115
+ settings_manager.user_config = {
116
+ "development": {
117
+ "url": "redis://localhost:6379",
118
+ "use_retry": True,
119
+ "retry_attempts": 3
120
+ },
121
+ "production": {
122
+ "url": "redis://prod-server:6379",
123
+ "use_retry": True,
124
+ "retry_attempts": 5,
125
+ "socket_timeout": 10.0
126
+ }
127
+ }
128
+
129
+ # Switch to production configuration
130
+ settings_manager.active_key = "production"
131
+ redis = get_redis()
132
+ ```
133
+
134
+ ### Runtime Overrides
135
+
136
+ ```python
137
+ from kiarina.lib.redis import get_redis
138
+
139
+ # Override settings at runtime
140
+ redis = get_redis(
141
+ url="redis://custom-server:6379",
142
+ use_retry=True,
143
+ decode_responses=True
144
+ )
145
+ ```
146
+
147
+ ## Advanced Usage
148
+
149
+ ### Connection Caching
150
+
151
+ ```python
152
+ from kiarina.lib.redis import get_redis
153
+
154
+ # These will return the same cached connection
155
+ redis1 = get_redis()
156
+ redis2 = get_redis()
157
+ assert redis1 is redis2
158
+
159
+ # Use different cache keys for separate connections
160
+ redis3 = get_redis(cache_key="secondary")
161
+ assert redis1 is not redis3
162
+ ```
163
+
164
+ ### Custom Configuration Keys
165
+
166
+ ```python
167
+ from kiarina.lib.redis import settings_manager, get_redis
168
+
169
+ # Configure multiple named configurations
170
+ settings_manager.user_config = {
171
+ "cache": {
172
+ "url": "redis://cache-db:6379",
173
+ "socket_timeout": 5.0
174
+ },
175
+ "session": {
176
+ "url": "redis://session-db:6379",
177
+ "socket_timeout": 10.0
178
+ }
179
+ }
180
+
181
+ # Use specific configurations
182
+ cache_redis = get_redis("cache")
183
+ session_redis = get_redis("session")
184
+ ```
185
+
186
+ ### Error Handling and Retries
187
+
188
+ ```python
189
+ from kiarina.lib.redis import get_redis
190
+ import redis
191
+
192
+ # Enable automatic retries for connection issues
193
+ redis_client = get_redis(use_retry=True)
194
+
195
+ try:
196
+ redis_client.set("key", "value")
197
+ value = redis_client.get("key")
198
+ except redis.ConnectionError as e:
199
+ print(f"Connection failed: {e}")
200
+ except redis.TimeoutError as e:
201
+ print(f"Operation timed out: {e}")
202
+ ```
203
+
204
+ ## Configuration Reference
205
+
206
+ | Setting | Environment Variable | Default | Description |
207
+ |---------|---------------------|---------|-------------|
208
+ | `url` | `KIARINA_LIB_REDIS_URL` | `"redis://localhost:6379"` | Redis connection URL |
209
+ | `use_retry` | `KIARINA_LIB_REDIS_USE_RETRY` | `false` | Enable automatic retries |
210
+ | `socket_timeout` | `KIARINA_LIB_REDIS_SOCKET_TIMEOUT` | `6.0` | Socket timeout in seconds |
211
+ | `socket_connect_timeout` | `KIARINA_LIB_REDIS_SOCKET_CONNECT_TIMEOUT` | `3.0` | Connection timeout in seconds |
212
+ | `health_check_interval` | `KIARINA_LIB_REDIS_HEALTH_CHECK_INTERVAL` | `60` | Health check interval in seconds |
213
+ | `retry_attempts` | `KIARINA_LIB_REDIS_RETRY_ATTEMPTS` | `3` | Number of retry attempts |
214
+ | `retry_delay` | `KIARINA_LIB_REDIS_RETRY_DELAY` | `1.0` | Delay between retries in seconds |
215
+
216
+ ## URL Formats
217
+
218
+ Redis URLs support the following formats:
219
+
220
+ - `redis://localhost:6379` - Basic connection
221
+ - `redis://username:password@localhost:6379` - With authentication
222
+ - `rediss://localhost:6379` - SSL/TLS connection
223
+ - `rediss://username:password@localhost:6379` - SSL/TLS with authentication
224
+ - `redis://localhost:6379/0` - Specify database number
225
+ - `unix:///path/to/socket.sock` - Unix socket connection
226
+
227
+ ## Development
228
+
229
+ ### Prerequisites
230
+
231
+ - Python 3.12+
232
+ - Docker (for running Redis in tests)
233
+
234
+ ### Setup
235
+
236
+ ```bash
237
+ # Clone the repository
238
+ git clone https://github.com/kiarina/kiarina-python.git
239
+ cd kiarina-python
240
+
241
+ # Setup development environment (installs tools, syncs dependencies, downloads test data)
242
+ mise run setup
243
+
244
+ # Start Redis for testing
245
+ docker compose up -d redis
246
+ ```
247
+
248
+ ### Running Tests
249
+
250
+ ```bash
251
+ # Run format, lint, type checks and tests
252
+ mise run package kiarina-lib-redis
253
+
254
+ # Coverage report
255
+ mise run package:test kiarina-lib-redis --coverage
256
+
257
+ # Run specific tests
258
+ uv run --group test pytest packages/kiarina-lib-redis/tests/test_sync.py
259
+ uv run --group test pytest packages/kiarina-lib-redis/tests/test_async.py
260
+ ```
261
+
262
+ ## Dependencies
263
+
264
+ - [redis](https://github.com/redis/redis-py) - Redis client for Python
265
+ - [pydantic-settings](https://docs.pydantic.dev/latest/concepts/pydantic_settings/) - Settings management
266
+ - [pydantic-settings-manager](https://github.com/kiarina/pydantic-settings-manager) - Advanced settings management
267
+
268
+ ## License
269
+
270
+ This project is licensed under the MIT License - see the [LICENSE](../../LICENSE) file for details.
271
+
272
+ ## Contributing
273
+
274
+ This is a personal project, but contributions are welcome! Please feel free to submit issues or pull requests.
275
+
276
+ ## Related Projects
277
+
278
+ - [kiarina-python](https://github.com/kiarina/kiarina-python) - The main monorepo containing this package
279
+ - [Redis](https://redis.io/) - The in-memory data structure store this library connects to
280
+ - [pydantic-settings-manager](https://github.com/kiarina/pydantic-settings-manager) - Configuration management library used by this package
@@ -0,0 +1,251 @@
1
+ # kiarina-lib-redis
2
+
3
+ A Python client library for [Redis](https://redis.io/) with configuration management and connection pooling.
4
+
5
+ ## Features
6
+
7
+ - **Configuration Management**: Use `pydantic-settings-manager` for flexible configuration
8
+ - **Connection Pooling**: Automatic connection caching and reuse
9
+ - **Retry Support**: Built-in retry mechanism for connection failures
10
+ - **Sync & Async**: Support for both synchronous and asynchronous operations
11
+ - **Type Safety**: Full type hints and Pydantic validation
12
+
13
+ ## Installation
14
+
15
+ ```bash
16
+ pip install kiarina-lib-redis
17
+ ```
18
+
19
+ ## Quick Start
20
+
21
+ ### Basic Usage (Sync)
22
+
23
+ ```python
24
+ from kiarina.lib.redis import get_redis
25
+
26
+ # Get a Redis client with default settings
27
+ redis = get_redis()
28
+
29
+ # Basic operations
30
+ redis.set("key", "value")
31
+ value = redis.get("key")
32
+ print(value) # b'value'
33
+
34
+ # With decode_responses=True for string values
35
+ redis = get_redis(decode_responses=True)
36
+ redis.set("key", "value")
37
+ value = redis.get("key")
38
+ print(value) # 'value'
39
+ ```
40
+
41
+ ### Async Usage
42
+
43
+ ```python
44
+ from kiarina.lib.redis.asyncio import get_redis
45
+
46
+ async def main():
47
+ # Get an async Redis client
48
+ redis = get_redis(decode_responses=True)
49
+
50
+ # Basic operations
51
+ await redis.set("key", "value")
52
+ value = await redis.get("key")
53
+ print(value) # 'value'
54
+ ```
55
+
56
+ ## Configuration
57
+
58
+ This library uses [pydantic-settings-manager](https://github.com/kiarina/pydantic-settings-manager) for flexible configuration management.
59
+
60
+ ### Environment Variables
61
+
62
+ Configure the Redis connection using environment variables:
63
+
64
+ ```bash
65
+ # Redis connection URL
66
+ export KIARINA_LIB_REDIS_URL="redis://localhost:6379"
67
+
68
+ # Enable retry mechanism
69
+ export KIARINA_LIB_REDIS_USE_RETRY="true"
70
+
71
+ # Timeout settings
72
+ export KIARINA_LIB_REDIS_SOCKET_TIMEOUT="6.0"
73
+ export KIARINA_LIB_REDIS_SOCKET_CONNECT_TIMEOUT="3.0"
74
+
75
+ # Retry settings
76
+ export KIARINA_LIB_REDIS_RETRY_ATTEMPTS="3"
77
+ export KIARINA_LIB_REDIS_RETRY_DELAY="1.0"
78
+ ```
79
+
80
+ ### Programmatic Configuration
81
+
82
+ ```python
83
+ from kiarina.lib.redis import settings_manager
84
+
85
+ # Configure for multiple environments
86
+ settings_manager.user_config = {
87
+ "development": {
88
+ "url": "redis://localhost:6379",
89
+ "use_retry": True,
90
+ "retry_attempts": 3
91
+ },
92
+ "production": {
93
+ "url": "redis://prod-server:6379",
94
+ "use_retry": True,
95
+ "retry_attempts": 5,
96
+ "socket_timeout": 10.0
97
+ }
98
+ }
99
+
100
+ # Switch to production configuration
101
+ settings_manager.active_key = "production"
102
+ redis = get_redis()
103
+ ```
104
+
105
+ ### Runtime Overrides
106
+
107
+ ```python
108
+ from kiarina.lib.redis import get_redis
109
+
110
+ # Override settings at runtime
111
+ redis = get_redis(
112
+ url="redis://custom-server:6379",
113
+ use_retry=True,
114
+ decode_responses=True
115
+ )
116
+ ```
117
+
118
+ ## Advanced Usage
119
+
120
+ ### Connection Caching
121
+
122
+ ```python
123
+ from kiarina.lib.redis import get_redis
124
+
125
+ # These will return the same cached connection
126
+ redis1 = get_redis()
127
+ redis2 = get_redis()
128
+ assert redis1 is redis2
129
+
130
+ # Use different cache keys for separate connections
131
+ redis3 = get_redis(cache_key="secondary")
132
+ assert redis1 is not redis3
133
+ ```
134
+
135
+ ### Custom Configuration Keys
136
+
137
+ ```python
138
+ from kiarina.lib.redis import settings_manager, get_redis
139
+
140
+ # Configure multiple named configurations
141
+ settings_manager.user_config = {
142
+ "cache": {
143
+ "url": "redis://cache-db:6379",
144
+ "socket_timeout": 5.0
145
+ },
146
+ "session": {
147
+ "url": "redis://session-db:6379",
148
+ "socket_timeout": 10.0
149
+ }
150
+ }
151
+
152
+ # Use specific configurations
153
+ cache_redis = get_redis("cache")
154
+ session_redis = get_redis("session")
155
+ ```
156
+
157
+ ### Error Handling and Retries
158
+
159
+ ```python
160
+ from kiarina.lib.redis import get_redis
161
+ import redis
162
+
163
+ # Enable automatic retries for connection issues
164
+ redis_client = get_redis(use_retry=True)
165
+
166
+ try:
167
+ redis_client.set("key", "value")
168
+ value = redis_client.get("key")
169
+ except redis.ConnectionError as e:
170
+ print(f"Connection failed: {e}")
171
+ except redis.TimeoutError as e:
172
+ print(f"Operation timed out: {e}")
173
+ ```
174
+
175
+ ## Configuration Reference
176
+
177
+ | Setting | Environment Variable | Default | Description |
178
+ |---------|---------------------|---------|-------------|
179
+ | `url` | `KIARINA_LIB_REDIS_URL` | `"redis://localhost:6379"` | Redis connection URL |
180
+ | `use_retry` | `KIARINA_LIB_REDIS_USE_RETRY` | `false` | Enable automatic retries |
181
+ | `socket_timeout` | `KIARINA_LIB_REDIS_SOCKET_TIMEOUT` | `6.0` | Socket timeout in seconds |
182
+ | `socket_connect_timeout` | `KIARINA_LIB_REDIS_SOCKET_CONNECT_TIMEOUT` | `3.0` | Connection timeout in seconds |
183
+ | `health_check_interval` | `KIARINA_LIB_REDIS_HEALTH_CHECK_INTERVAL` | `60` | Health check interval in seconds |
184
+ | `retry_attempts` | `KIARINA_LIB_REDIS_RETRY_ATTEMPTS` | `3` | Number of retry attempts |
185
+ | `retry_delay` | `KIARINA_LIB_REDIS_RETRY_DELAY` | `1.0` | Delay between retries in seconds |
186
+
187
+ ## URL Formats
188
+
189
+ Redis URLs support the following formats:
190
+
191
+ - `redis://localhost:6379` - Basic connection
192
+ - `redis://username:password@localhost:6379` - With authentication
193
+ - `rediss://localhost:6379` - SSL/TLS connection
194
+ - `rediss://username:password@localhost:6379` - SSL/TLS with authentication
195
+ - `redis://localhost:6379/0` - Specify database number
196
+ - `unix:///path/to/socket.sock` - Unix socket connection
197
+
198
+ ## Development
199
+
200
+ ### Prerequisites
201
+
202
+ - Python 3.12+
203
+ - Docker (for running Redis in tests)
204
+
205
+ ### Setup
206
+
207
+ ```bash
208
+ # Clone the repository
209
+ git clone https://github.com/kiarina/kiarina-python.git
210
+ cd kiarina-python
211
+
212
+ # Setup development environment (installs tools, syncs dependencies, downloads test data)
213
+ mise run setup
214
+
215
+ # Start Redis for testing
216
+ docker compose up -d redis
217
+ ```
218
+
219
+ ### Running Tests
220
+
221
+ ```bash
222
+ # Run format, lint, type checks and tests
223
+ mise run package kiarina-lib-redis
224
+
225
+ # Coverage report
226
+ mise run package:test kiarina-lib-redis --coverage
227
+
228
+ # Run specific tests
229
+ uv run --group test pytest packages/kiarina-lib-redis/tests/test_sync.py
230
+ uv run --group test pytest packages/kiarina-lib-redis/tests/test_async.py
231
+ ```
232
+
233
+ ## Dependencies
234
+
235
+ - [redis](https://github.com/redis/redis-py) - Redis client for Python
236
+ - [pydantic-settings](https://docs.pydantic.dev/latest/concepts/pydantic_settings/) - Settings management
237
+ - [pydantic-settings-manager](https://github.com/kiarina/pydantic-settings-manager) - Advanced settings management
238
+
239
+ ## License
240
+
241
+ This project is licensed under the MIT License - see the [LICENSE](../../LICENSE) file for details.
242
+
243
+ ## Contributing
244
+
245
+ This is a personal project, but contributions are welcome! Please feel free to submit issues or pull requests.
246
+
247
+ ## Related Projects
248
+
249
+ - [kiarina-python](https://github.com/kiarina/kiarina-python) - The main monorepo containing this package
250
+ - [Redis](https://redis.io/) - The in-memory data structure store this library connects to
251
+ - [pydantic-settings-manager](https://github.com/kiarina/pydantic-settings-manager) - Configuration management library used by this package
@@ -0,0 +1,45 @@
1
+ [project]
2
+ name = "kiarina-lib-redis"
3
+ version = "1.0.0"
4
+ description = "Redis client library for kiarina namespace"
5
+ readme = "README.md"
6
+ license = { text = "MIT" }
7
+ authors = [
8
+ { name = "kiarina", email = "kiarinadawa@gmail.com" }
9
+ ]
10
+ maintainers = [
11
+ { name = "kiarina", email = "kiarinadawa@gmail.com" }
12
+ ]
13
+ keywords = ["redis", "client", "pydantic", "settings", "database", "cache", "async"]
14
+ classifiers = [
15
+ "Development Status :: 4 - Beta",
16
+ "Intended Audience :: Developers",
17
+ "License :: OSI Approved :: MIT License",
18
+ "Operating System :: OS Independent",
19
+ "Programming Language :: Python :: 3",
20
+ "Programming Language :: Python :: 3.12",
21
+ "Programming Language :: Python :: 3.13",
22
+ "Topic :: Database",
23
+ "Topic :: Software Development :: Libraries :: Python Modules",
24
+ "Typing :: Typed",
25
+ ]
26
+ requires-python = ">=3.12"
27
+ dependencies = [
28
+ "pydantic-settings>=2.10.1",
29
+ "pydantic-settings-manager>=2.1.0",
30
+ "redis>=6.4.0",
31
+ ]
32
+
33
+ [project.urls]
34
+ Homepage = "https://github.com/kiarina/kiarina-python"
35
+ Repository = "https://github.com/kiarina/kiarina-python"
36
+ Issues = "https://github.com/kiarina/kiarina-python/issues"
37
+ Changelog = "https://github.com/kiarina/kiarina-python/blob/main/packages/kiarina-lib-redis/CHANGELOG.md"
38
+ Documentation = "https://github.com/kiarina/kiarina-python/tree/main/packages/kiarina-lib-redis#readme"
39
+
40
+ [build-system]
41
+ requires = ["hatchling"]
42
+ build-backend = "hatchling.build"
43
+
44
+ [tool.hatch.build.targets.wheel]
45
+ packages = ["src/kiarina"]
@@ -0,0 +1,27 @@
1
+ import logging
2
+ from importlib import import_module
3
+ from importlib.metadata import version
4
+ from typing import TYPE_CHECKING
5
+
6
+ if TYPE_CHECKING:
7
+ from ._sync.registry import get_redis
8
+ from .settings import settings_manager
9
+
10
+ __version__ = version("kiarina-lib-redis")
11
+
12
+ __all__ = ["get_redis", "settings_manager"]
13
+
14
+ logging.getLogger(__name__).addHandler(logging.NullHandler())
15
+
16
+
17
+ def __getattr__(name: str) -> object:
18
+ if name not in __all__:
19
+ raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
20
+
21
+ module_map = {
22
+ "get_redis": "._sync.registry",
23
+ "settings_manager": ".settings",
24
+ }
25
+
26
+ globals()[name] = getattr(import_module(module_map[name], __name__), name)
27
+ return globals()[name]
@@ -0,0 +1,36 @@
1
+ from typing import Any
2
+
3
+ import redis.asyncio as redis
4
+
5
+ from .._core.registry import get_redis as _get_redis
6
+
7
+
8
+ def get_redis(
9
+ config_key: str | None = None,
10
+ *,
11
+ cache_key: str | None = None,
12
+ use_retry: bool | None = None,
13
+ url: str | None = None,
14
+ **kwargs: Any,
15
+ ) -> redis.Redis:
16
+ """
17
+ Get a Redis client.
18
+
19
+ Args:
20
+ config_key (str | None): The configuration key for the Redis client.
21
+ cache_key (str | None): The cache key for the Redis client.
22
+ use_retry (bool | None): Whether to use retry for the Redis client.
23
+ url (str | None): The Redis URL.
24
+ **kwargs: Additional keyword arguments for the Redis client.
25
+
26
+ Returns:
27
+ redis.Redis: The Redis client.
28
+ """
29
+ return _get_redis(
30
+ "async",
31
+ config_key,
32
+ cache_key=cache_key,
33
+ use_retry=use_retry,
34
+ url=url,
35
+ **kwargs,
36
+ )
@@ -0,0 +1,101 @@
1
+ from typing import Any, Literal, overload
2
+
3
+ import redis
4
+ import redis.asyncio
5
+ from redis.backoff import ExponentialBackoff
6
+ from redis.retry import Retry
7
+
8
+ from ..settings import settings_manager
9
+
10
+ _sync_cache: dict[str, redis.Redis] = {}
11
+ """
12
+ Sync Redis clients cache
13
+ """
14
+
15
+ _async_cache: dict[str, redis.asyncio.Redis] = {}
16
+ """
17
+ Async Redis clients cache
18
+ """
19
+
20
+
21
+ @overload
22
+ def get_redis(
23
+ mode: Literal["sync"],
24
+ config_key: str | None = None,
25
+ *,
26
+ cache_key: str | None = None,
27
+ use_retry: bool | None = None,
28
+ url: str | None = None,
29
+ **kwargs: Any,
30
+ ) -> redis.Redis: ...
31
+
32
+
33
+ @overload
34
+ def get_redis(
35
+ mode: Literal["async"],
36
+ config_key: str | None = None,
37
+ *,
38
+ cache_key: str | None = None,
39
+ use_retry: bool | None = None,
40
+ url: str | None = None,
41
+ **kwargs: Any,
42
+ ) -> redis.asyncio.Redis: ...
43
+
44
+
45
+ def get_redis(
46
+ mode: Literal["sync", "async"],
47
+ config_key: str | None = None,
48
+ *,
49
+ cache_key: str | None = None,
50
+ use_retry: bool | None = None,
51
+ url: str | None = None,
52
+ **kwargs: Any,
53
+ ) -> redis.Redis | redis.asyncio.Redis:
54
+ """
55
+ Get a Redis client with shared logic.
56
+ """
57
+ settings = settings_manager.get_settings_by_key(config_key)
58
+
59
+ if url is None:
60
+ url = settings.url
61
+
62
+ if use_retry is None:
63
+ use_retry = settings.use_retry
64
+
65
+ params = {**settings.initialize_params, **kwargs}
66
+
67
+ if use_retry:
68
+ params.update(
69
+ {
70
+ "socket_timeout": settings.socket_timeout,
71
+ "socket_connect_timeout": settings.socket_connect_timeout,
72
+ "health_check_interval": settings.health_check_interval,
73
+ "retry": Retry(
74
+ ExponentialBackoff(cap=settings.retry_delay),
75
+ settings.retry_attempts,
76
+ ),
77
+ }
78
+ )
79
+
80
+ if mode == "sync":
81
+ params["retry_on_error"] = [redis.ConnectionError, redis.TimeoutError]
82
+ else:
83
+ params["retry_on_error"] = [
84
+ redis.asyncio.ConnectionError,
85
+ redis.asyncio.TimeoutError,
86
+ ]
87
+
88
+ if cache_key is None:
89
+ cache_key = url
90
+
91
+ if mode == "sync":
92
+ if cache_key not in _sync_cache:
93
+ _sync_cache[cache_key] = redis.Redis.from_url(url, **params)
94
+
95
+ return _sync_cache[cache_key]
96
+
97
+ else:
98
+ if cache_key not in _async_cache:
99
+ _async_cache[cache_key] = redis.asyncio.Redis.from_url(url, **params)
100
+
101
+ return _async_cache[cache_key]
@@ -0,0 +1,36 @@
1
+ from typing import Any
2
+
3
+ import redis
4
+
5
+ from .._core.registry import get_redis as _get_redis
6
+
7
+
8
+ def get_redis(
9
+ config_key: str | None = None,
10
+ *,
11
+ cache_key: str | None = None,
12
+ use_retry: bool | None = None,
13
+ url: str | None = None,
14
+ **kwargs: Any,
15
+ ) -> redis.Redis:
16
+ """
17
+ Get a Redis client.
18
+
19
+ Args:
20
+ config_key (str | None): The configuration key for the Redis client.
21
+ cache_key (str | None): The cache key for the Redis client.
22
+ use_retry (bool | None): Whether to use retry for the Redis client.
23
+ url (str | None): The Redis URL.
24
+ **kwargs: Additional keyword arguments for the Redis client.
25
+
26
+ Returns:
27
+ redis.Redis: The Redis client.
28
+ """
29
+ return _get_redis(
30
+ "sync",
31
+ config_key,
32
+ cache_key=cache_key,
33
+ use_retry=use_retry,
34
+ url=url,
35
+ **kwargs,
36
+ )
@@ -0,0 +1,25 @@
1
+ import logging
2
+ from importlib import import_module
3
+ from typing import TYPE_CHECKING
4
+
5
+ if TYPE_CHECKING:
6
+ from ._async.registry import get_redis
7
+ from .settings import settings_manager
8
+
9
+ __all__ = ["get_redis", "settings_manager"]
10
+
11
+ logging.getLogger(__name__).addHandler(logging.NullHandler())
12
+
13
+
14
+ def __getattr__(name: str) -> object:
15
+ if name not in __all__:
16
+ raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
17
+
18
+ module_map = {
19
+ "get_redis": "._async.registry",
20
+ "settings_manager": ".settings",
21
+ }
22
+
23
+ parent = __name__.rsplit(".", 1)[0]
24
+ globals()[name] = getattr(import_module(module_map[name], parent), name)
25
+ return globals()[name]
File without changes
@@ -0,0 +1,70 @@
1
+ from typing import Any
2
+
3
+ from pydantic import Field
4
+ from pydantic_settings import BaseSettings, SettingsConfigDict
5
+ from pydantic_settings_manager import SettingsManager
6
+
7
+
8
+ class RedisSettings(BaseSettings):
9
+ """
10
+ Redis Settings
11
+ """
12
+
13
+ model_config = SettingsConfigDict(env_prefix="KIARINA_LIB_REDIS_")
14
+
15
+ url: str = "redis://localhost:6379"
16
+ """
17
+ Redis URL
18
+
19
+ Example:
20
+ - redis://[[username]:[password]]@localhost:6379
21
+ - rediss://[[username]:[password]]@localhost:6379
22
+ """
23
+
24
+ initialize_params: dict[str, Any] = Field(default_factory=dict)
25
+ """
26
+ Additional parameters to initialize the Redis client.
27
+ """
28
+
29
+ use_retry: bool = False
30
+ """
31
+ Whether to enable automatic retries
32
+
33
+ When enabled, it is configured to retry upon occurrence of
34
+ redis.ConnectionError or redis.TimeoutError.
35
+ """
36
+
37
+ socket_timeout: float = 6.0
38
+ """
39
+ Socket timeout in seconds
40
+
41
+ After sending a command, if this time is exceeded, a redis.TimeoutError will be raised.
42
+ """
43
+
44
+ socket_connect_timeout: float = 3.0
45
+ """
46
+ Socket connection timeout in seconds
47
+
48
+ If this time is exceeded when establishing a new connection, a redis.ConnectionError will occur.
49
+ """
50
+
51
+ health_check_interval: int = 60
52
+ """
53
+ Health check interval in seconds
54
+
55
+ When acquiring a connection from the pool,
56
+ if the time since last use has elapsed, execute a PING to verify the connection status.
57
+ """
58
+
59
+ retry_attempts: int = 3
60
+ """
61
+ Number of retry attempts
62
+ """
63
+
64
+ retry_delay: float = 1.0
65
+ """
66
+ Delay between retry attempts in seconds
67
+ """
68
+
69
+
70
+ settings_manager = SettingsManager(RedisSettings, multi=True)
File without changes
File without changes
@@ -0,0 +1,17 @@
1
+ from kiarina.lib.redis.asyncio import get_redis
2
+
3
+
4
+ async def test_get_redis():
5
+ # Check if it is cached
6
+ redis1 = get_redis(use_retry=True, decode_responses=True)
7
+ redis2 = get_redis()
8
+ assert redis1 is redis2
9
+
10
+ # Verify that changing the cache key allows retrieval of a different instance
11
+ redis3 = get_redis(cache_key="other")
12
+ assert redis1 is not redis3
13
+
14
+ # Test basic set and get operations
15
+ await redis1.set("test_get_redis", "hello")
16
+ value = await redis1.get("test_get_redis")
17
+ assert value == "hello"
@@ -0,0 +1,17 @@
1
+ from kiarina.lib.redis import get_redis
2
+
3
+
4
+ def test_get_redis():
5
+ # Check if it is cached
6
+ redis1 = get_redis(use_retry=True, decode_responses=True)
7
+ redis2 = get_redis()
8
+ assert redis1 is redis2
9
+
10
+ # Verify that changing the cache key allows retrieval of a different instance
11
+ redis3 = get_redis(cache_key="other")
12
+ assert redis1 is not redis3
13
+
14
+ # Test basic set and get operations
15
+ redis1.set("test_get_redis", "hello")
16
+ value = redis1.get("test_get_redis")
17
+ assert value == "hello"