-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* add redis extension * add redis documentation
- Loading branch information
1 parent
b53c73a
commit 08b19e1
Showing
26 changed files
with
923 additions
and
91 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,214 @@ | ||
# Redis | ||
|
||
This extension provides support for connecting to Redis servers. It registers the | ||
`redis.asyncio.Redis` service. | ||
|
||
## Usage | ||
|
||
First install the `redis` extra: | ||
|
||
```shell | ||
pip install selva[redis] | ||
``` | ||
|
||
Define the configuration properties: | ||
|
||
=== "configuration/settings.yaml" | ||
|
||
```yaml | ||
extensions: | ||
- selva.ext.data.redis # (1) | ||
|
||
data: | ||
redis: | ||
default: # (2) | ||
url: redis://localhost:6379/0 | ||
other: # (3) | ||
url: redis://localhost:6379/1 | ||
``` | ||
|
||
1. Activate the sqlalchemy extension | ||
2. "default" connection will be registered without a name | ||
3. Connection registered with name "other" | ||
|
||
Inject the `Redis` service: | ||
|
||
```python | ||
from typing import Annotated | ||
from redis.asyncio import Redis | ||
from selva.di import service, Inject | ||
|
||
|
||
@service | ||
class MyService: | ||
# default service | ||
redis: Annotated[Redis, Inject] | ||
|
||
# named service | ||
other_redis: Annotated[Redis, Inject(name="other")] | ||
``` | ||
|
||
Redis connections can also be defined with username and password separated from | ||
the url, or even with individual components: | ||
|
||
=== "configuration/settings.yaml" | ||
|
||
```yaml | ||
data: | ||
redis: | ||
url_username_password: # (1) | ||
url: redis://localhost:6379/0 | ||
username: user | ||
password: pass | ||
|
||
individual_components: # (2) | ||
host: localhost | ||
port: 6379 | ||
db: 0 | ||
username: user | ||
password: pass | ||
``` | ||
|
||
1. Username and password separated from the redis url | ||
2. Each component defined individually | ||
|
||
## Using environment variables | ||
|
||
=== "configuration/settings.yaml" | ||
|
||
```yaml | ||
data: | ||
redis: | ||
default: | ||
url: "${REDIS_URL}" # (1) | ||
|
||
other: # (2) | ||
url: "${REDIS_URL}" | ||
username: "${REDIS_USERNAME}" | ||
password: "${REDIS_PASSWORD}" | ||
|
||
another: # (3) | ||
host: "${REDIS_HOST}" | ||
port: ${REDIS_PORT} | ||
db: "${REDIS_DB}" | ||
username: "${REDIS_USERNAME}" | ||
password: "${REDIS_PASSWORD}" | ||
``` | ||
|
||
1. Can be define with just the environment variable `SELVA__DATA__REDIS__DEFAULT__URL` | ||
2. Can be defined with just the environment variables: | ||
- `SELVA__DATA__REDIS__OTHER__URL` | ||
- `SELVA__DATA__REDIS__OTHER__USERNAME` | ||
- `SELVA__DATA__REDIS__OTHER__PASSWORD` | ||
3. Can be defined with just the environment variables: | ||
- `SELVA__DATA__REDIS__ANOTHER__HOST` | ||
- `SELVA__DATA__REDIS__ANOTHER__PORT` | ||
- `SELVA__DATA__REDIS__ANOTHER__DB` | ||
- `SELVA__DATA__REDIS__ANOTHER__USERNAME` | ||
- `SELVA__DATA__REDIS__ANOTHER__PASSWORD` | ||
|
||
## Example | ||
|
||
=== "application/controller.py" | ||
|
||
```python | ||
from typing import Annotated | ||
|
||
from redis.asyncio import Redis | ||
|
||
from asgikit.responses import respond_json | ||
|
||
from selva.di import Inject | ||
from selva.web import controller, get | ||
|
||
|
||
@controller | ||
class Controller: | ||
redis: Annotated[Redis, Inject] | ||
|
||
async def initialize(self): | ||
await self.redis.set("number", 0, nx=True, ex=60) | ||
|
||
@get | ||
async def index(self, request): | ||
number = await self.redis.incr("number") | ||
await respond_json(request.response, {"number": number}) | ||
``` | ||
|
||
=== "configuration/settings.yaml" | ||
|
||
```yaml | ||
data: | ||
redis: | ||
default: | ||
url: "redis://localhost:6379/0" | ||
``` | ||
|
||
## Configuration options | ||
|
||
Selva offers several options to configure Redis. If you need more control over | ||
the SQLAlchemy services, you can create your own `redis.asyncio.Redis` outside | ||
of the DI context. | ||
|
||
The available options are shown below: | ||
|
||
```yaml | ||
data: | ||
redis: | ||
default: | ||
url: "" | ||
host: "" | ||
port: 6379 | ||
db: 0 | ||
username: "" | ||
password: "" | ||
options: # (1) | ||
socket_timeout: 1.0 | ||
socket_connect_timeout: 1.0 | ||
socket_keepalive: false | ||
socket_keepalive_options: {} | ||
unix_socket_path: "" | ||
encoding: "" | ||
encoding_errors: "strict" # or "ignore", "replace" | ||
decode_responses: false | ||
retry_on_timeout: false | ||
retry_on_error: [] | ||
ssl: false | ||
ssl_keyfile: "" | ||
ssl_certfile: "" | ||
ssl_cert_reqs: "" | ||
ssl_ca_certs: "" | ||
ssl_ca_data: "" | ||
ssl_check_hostname: false | ||
max_connections: 1 | ||
single_connection_client: false | ||
health_check_interval: 1 | ||
client_name: "" | ||
lib_name: "" | ||
lib_version: "" | ||
auto_close_connection_pool: false | ||
protocol: 3 | ||
retry: | ||
retries: 1 | ||
supported_errors: [] # (2) | ||
backoff: # (3) | ||
no_backoff: | ||
constant: | ||
backoff: 1 | ||
exponential: | ||
cap: 1 | ||
base: 1 | ||
full_jitter: | ||
cap: 1 | ||
base: 1 | ||
equal_jitter: | ||
cap: 1 | ||
base: 1 | ||
decorrelated_jitter: | ||
cap: 1 | ||
base: 1 | ||
``` | ||
1. `options` values are described in [`redis.asyncio.Redis`](https://redis.readthedocs.io/en/stable/connections.html#async-client). | ||
2. Dotted path to python classes. | ||
3. Only one option in `backoff` should be set. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
from typing import Annotated | ||
|
||
from asgikit.responses import respond_json | ||
from selva.di import Inject | ||
from selva.web import controller, get | ||
|
||
from .service import RedisService | ||
|
||
|
||
@controller | ||
class Controller: | ||
redis_service: Annotated[RedisService, Inject] | ||
|
||
@get | ||
async def index(self, request): | ||
number = await self.redis_service.get_incr() | ||
await respond_json(request.response, {"number": number}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
from typing import Annotated | ||
|
||
from redis.asyncio import Redis | ||
|
||
from selva.di import service, Inject | ||
|
||
|
||
@service | ||
class RedisService: | ||
redis: Annotated[Redis, Inject] | ||
|
||
async def initialize(self): | ||
await self.redis.set("number", 0, ex=60) | ||
|
||
async def get_incr(self) -> int: | ||
return await self.redis.incr("number") | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
extensions: | ||
- selva.ext.data.redis | ||
|
||
data: | ||
redis: | ||
default: | ||
host: "localhost" | ||
options: | ||
retry: | ||
retries: 1 | ||
backoff: | ||
constant: | ||
backoff: 1 | ||
|
||
other: | ||
url: "redis://localhost:6379/1" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.