unfazed-taskiq 0.0.1__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.
- unfazed_taskiq-0.0.1/.env +1 -0
- unfazed_taskiq-0.0.1/.github/workflows/publish.yml +18 -0
- unfazed_taskiq-0.0.1/.github/workflows/test.yml +46 -0
- unfazed_taskiq-0.0.1/.gitignore +12 -0
- unfazed_taskiq-0.0.1/Dockerfile +9 -0
- unfazed_taskiq-0.0.1/Makefile +16 -0
- unfazed_taskiq-0.0.1/PKG-INFO +95 -0
- unfazed_taskiq-0.0.1/README.md +85 -0
- unfazed_taskiq-0.0.1/docker-compose.yml +25 -0
- unfazed_taskiq-0.0.1/pyproject.toml +80 -0
- unfazed_taskiq-0.0.1/tests/conftest.py +13 -0
- unfazed_taskiq-0.0.1/tests/proj/app1/app.py +6 -0
- unfazed_taskiq-0.0.1/tests/proj/app1/endpoints.py +11 -0
- unfazed_taskiq-0.0.1/tests/proj/app1/routes.py +7 -0
- unfazed_taskiq-0.0.1/tests/proj/app1/tasks.py +11 -0
- unfazed_taskiq-0.0.1/tests/proj/entry/__init__.py +0 -0
- unfazed_taskiq-0.0.1/tests/proj/entry/routes.py +5 -0
- unfazed_taskiq-0.0.1/tests/proj/entry/settings.py +27 -0
- unfazed_taskiq-0.0.1/tests/proj/entry2/routes.py +5 -0
- unfazed_taskiq-0.0.1/tests/proj/entry2/settings.py +18 -0
- unfazed_taskiq-0.0.1/tests/proj/manage.py +33 -0
- unfazed_taskiq-0.0.1/tests/test_taskiq/test_api.py +29 -0
- unfazed_taskiq-0.0.1/tests/test_taskiq/test_base.py +42 -0
- unfazed_taskiq-0.0.1/tests/test_taskiq/test_cli.py +51 -0
- unfazed_taskiq-0.0.1/unfazed_taskiq/__init__.py +4 -0
- unfazed_taskiq-0.0.1/unfazed_taskiq/base.py +80 -0
- unfazed_taskiq-0.0.1/unfazed_taskiq/cli.py +40 -0
- unfazed_taskiq-0.0.1/unfazed_taskiq/lifespan.py +21 -0
- unfazed_taskiq-0.0.1/unfazed_taskiq/settings.py +26 -0
- unfazed_taskiq-0.0.1/uv.lock +976 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
COMPOSE_PROJECT_NAME=unfazed_taskiq
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
on:
|
|
3
|
+
push:
|
|
4
|
+
tags:
|
|
5
|
+
- "v[0-9]+.[0-9]+.[0-9]+" # 更精确的版本号匹配
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
build:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
steps:
|
|
11
|
+
- uses: actions/checkout@v4
|
|
12
|
+
- name: Build and publish to pypi
|
|
13
|
+
uses: astral-sh/setup-uv@v5
|
|
14
|
+
- run: |
|
|
15
|
+
uv build
|
|
16
|
+
uv publish
|
|
17
|
+
env:
|
|
18
|
+
UV_PUBLISH_TOKEN: ${{ secrets.PYPI_TOKEN }}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
name: Test Unfazed Taskiq
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: ["main"]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: ["main"]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
tests:
|
|
11
|
+
services:
|
|
12
|
+
rabbitmq:
|
|
13
|
+
image: rabbitmq:3-management-alpine
|
|
14
|
+
env:
|
|
15
|
+
RABBITMQ_DEFAULT_USER: guest
|
|
16
|
+
RABBITMQ_DEFAULT_PASS: guest
|
|
17
|
+
ports: ['5672:5672', '15672:15672']
|
|
18
|
+
redis:
|
|
19
|
+
image: redis
|
|
20
|
+
ports: ['6379:6379']
|
|
21
|
+
name: "Python ${{ matrix.python-version }}"
|
|
22
|
+
runs-on: "ubuntu-latest"
|
|
23
|
+
|
|
24
|
+
strategy:
|
|
25
|
+
matrix:
|
|
26
|
+
python-version: ["3.12"]
|
|
27
|
+
|
|
28
|
+
steps:
|
|
29
|
+
- uses: "actions/checkout@v4"
|
|
30
|
+
- uses: "actions/setup-python@v5"
|
|
31
|
+
with:
|
|
32
|
+
python-version: "${{ matrix.python-version }}"
|
|
33
|
+
allow-prereleases: true
|
|
34
|
+
- name: "Install dependencies"
|
|
35
|
+
run: |
|
|
36
|
+
pip install uv
|
|
37
|
+
uv sync
|
|
38
|
+
- name: "Run format"
|
|
39
|
+
run: make format
|
|
40
|
+
- name: "Run Test"
|
|
41
|
+
run: make test
|
|
42
|
+
env:
|
|
43
|
+
UNFAZED_SETTINGS_MODULE: "tests.proj.entry.settings"
|
|
44
|
+
REDIS_HOST: "localhost"
|
|
45
|
+
RABBITMQ_HOST: "localhost"
|
|
46
|
+
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
all: test
|
|
2
|
+
|
|
3
|
+
test:
|
|
4
|
+
@echo "Running tests..."
|
|
5
|
+
uv run pytest -v -s --cov ./unfazed_taskiq --cov-report term-missing
|
|
6
|
+
|
|
7
|
+
format:
|
|
8
|
+
@echo "Formatting code..."
|
|
9
|
+
uv run ruff format tests/ unfazed_taskiq/
|
|
10
|
+
uv run ruff check tests/ unfazed_taskiq/ --fix
|
|
11
|
+
uv run mypy --check-untyped-defs --explicit-package-bases --ignore-missing-imports tests/ unfazed_taskiq/
|
|
12
|
+
|
|
13
|
+
publish:
|
|
14
|
+
@echo "Publishing package..."
|
|
15
|
+
uv build
|
|
16
|
+
uv publish
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: unfazed-taskiq
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: Taskiq Plugin for Unfazed
|
|
5
|
+
Requires-Python: >=3.12
|
|
6
|
+
Requires-Dist: taskiq-aio-pika>=0.4.2
|
|
7
|
+
Requires-Dist: taskiq>=0.11.16
|
|
8
|
+
Requires-Dist: unfazed>=0.0.8
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
|
|
11
|
+
Unfazed Taskiq
|
|
12
|
+
===============
|
|
13
|
+
|
|
14
|
+
taskiq wrapper with unfazed.
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
Installation
|
|
18
|
+
------------
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
pip install unfazed-taskiq
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
Quick Start
|
|
26
|
+
-----
|
|
27
|
+
|
|
28
|
+
Add settings to your unfazed settings file:
|
|
29
|
+
|
|
30
|
+
```python
|
|
31
|
+
# entry/settings.py
|
|
32
|
+
UNFAZED_TASKIQ_SETTINGS = {
|
|
33
|
+
"BROKER": {
|
|
34
|
+
"BACKEND": "taskiq.InMemoryBroker",
|
|
35
|
+
"OPTIONS": {},
|
|
36
|
+
},
|
|
37
|
+
"RESULT": {
|
|
38
|
+
"BACKEND": "taskiq_redis.RedisAsyncResultBackend",
|
|
39
|
+
"OPTIONS": {
|
|
40
|
+
"redis_url": "redis://redis:6379",
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
"SCHEDULER": {
|
|
44
|
+
"BACKEND": "taskiq.scheduler.scheduler.TaskiqScheduler",
|
|
45
|
+
"SOURCES_CLS": ["taskiq.schedule_sources.LabelScheduleSource"],
|
|
46
|
+
},
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
# add lifespan to your settings
|
|
50
|
+
UNFAZED_SETTINGS = {
|
|
51
|
+
"LIFESPAN": ["unfazed_taskiq.lifespan.TaskiqLifeSpan"],
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Use UnfazedTaskiqAgent in your app's `tasks.py`:
|
|
57
|
+
|
|
58
|
+
```python
|
|
59
|
+
# app/tasks.py
|
|
60
|
+
from unfazed_taskiq import agent
|
|
61
|
+
|
|
62
|
+
@agent.broker.task
|
|
63
|
+
async def add(a: int, b: int) -> int:
|
|
64
|
+
return a + b
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
@agent.broker.task(schedule=[{"crontab": "*/1 * * * *", "args": [1, 2]}])
|
|
68
|
+
async def add_schedule(a: int, b: int) -> int:
|
|
69
|
+
return a + b
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
Kick off tasks
|
|
75
|
+
|
|
76
|
+
```python
|
|
77
|
+
|
|
78
|
+
from .tasks import add
|
|
79
|
+
|
|
80
|
+
async def your_service():
|
|
81
|
+
await add.kiq(1, 2)
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
Start Taskiq Worker or Scheduler
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
taskiq worker unfazed_taskiq.cli:broker
|
|
90
|
+
|
|
91
|
+
# or
|
|
92
|
+
taskiq scheduler unfazed_taskiq.cli:scheduler
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
Unfazed Taskiq
|
|
2
|
+
===============
|
|
3
|
+
|
|
4
|
+
taskiq wrapper with unfazed.
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
Installation
|
|
8
|
+
------------
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
pip install unfazed-taskiq
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
Quick Start
|
|
16
|
+
-----
|
|
17
|
+
|
|
18
|
+
Add settings to your unfazed settings file:
|
|
19
|
+
|
|
20
|
+
```python
|
|
21
|
+
# entry/settings.py
|
|
22
|
+
UNFAZED_TASKIQ_SETTINGS = {
|
|
23
|
+
"BROKER": {
|
|
24
|
+
"BACKEND": "taskiq.InMemoryBroker",
|
|
25
|
+
"OPTIONS": {},
|
|
26
|
+
},
|
|
27
|
+
"RESULT": {
|
|
28
|
+
"BACKEND": "taskiq_redis.RedisAsyncResultBackend",
|
|
29
|
+
"OPTIONS": {
|
|
30
|
+
"redis_url": "redis://redis:6379",
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
"SCHEDULER": {
|
|
34
|
+
"BACKEND": "taskiq.scheduler.scheduler.TaskiqScheduler",
|
|
35
|
+
"SOURCES_CLS": ["taskiq.schedule_sources.LabelScheduleSource"],
|
|
36
|
+
},
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
# add lifespan to your settings
|
|
40
|
+
UNFAZED_SETTINGS = {
|
|
41
|
+
"LIFESPAN": ["unfazed_taskiq.lifespan.TaskiqLifeSpan"],
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Use UnfazedTaskiqAgent in your app's `tasks.py`:
|
|
47
|
+
|
|
48
|
+
```python
|
|
49
|
+
# app/tasks.py
|
|
50
|
+
from unfazed_taskiq import agent
|
|
51
|
+
|
|
52
|
+
@agent.broker.task
|
|
53
|
+
async def add(a: int, b: int) -> int:
|
|
54
|
+
return a + b
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
@agent.broker.task(schedule=[{"crontab": "*/1 * * * *", "args": [1, 2]}])
|
|
58
|
+
async def add_schedule(a: int, b: int) -> int:
|
|
59
|
+
return a + b
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
Kick off tasks
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
|
|
68
|
+
from .tasks import add
|
|
69
|
+
|
|
70
|
+
async def your_service():
|
|
71
|
+
await add.kiq(1, 2)
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
Start Taskiq Worker or Scheduler
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
taskiq worker unfazed_taskiq.cli:broker
|
|
80
|
+
|
|
81
|
+
# or
|
|
82
|
+
taskiq scheduler unfazed_taskiq.cli:scheduler
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
services:
|
|
2
|
+
rabbitmq:
|
|
3
|
+
image: rabbitmq:3-management-alpine
|
|
4
|
+
environment:
|
|
5
|
+
- RABBITMQ_DEFAULT_USER=guest
|
|
6
|
+
- RABBITMQ_DEFAULT_PASS=guest
|
|
7
|
+
ports:
|
|
8
|
+
- 5672:5672
|
|
9
|
+
- 15672:15672
|
|
10
|
+
redis:
|
|
11
|
+
image: redis:latest
|
|
12
|
+
ports:
|
|
13
|
+
- 6379:6379
|
|
14
|
+
app:
|
|
15
|
+
build: .
|
|
16
|
+
ports:
|
|
17
|
+
- "127.0.0.1:9927:9927"
|
|
18
|
+
depends_on:
|
|
19
|
+
- rabbitmq
|
|
20
|
+
- redis
|
|
21
|
+
command: tail -f /unfazed_taskiq/README.md
|
|
22
|
+
environment:
|
|
23
|
+
- UNFAZED_SETTINGS_MODULE=tests.proj.entry.settings
|
|
24
|
+
volumes:
|
|
25
|
+
- .:/unfazed_taskiq
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "unfazed-taskiq"
|
|
3
|
+
version = "0.0.1"
|
|
4
|
+
description = "Taskiq Plugin for Unfazed"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.12"
|
|
7
|
+
dependencies = [
|
|
8
|
+
"taskiq>=0.11.16",
|
|
9
|
+
"taskiq-aio-pika>=0.4.2",
|
|
10
|
+
"unfazed>=0.0.8",
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
[build-system]
|
|
15
|
+
requires = ["hatchling"]
|
|
16
|
+
build-backend = "hatchling.build"
|
|
17
|
+
|
|
18
|
+
[tool.hatch.build.targets.wheel]
|
|
19
|
+
packages = ["unfazed_taskiq"]
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
[dependency-groups]
|
|
23
|
+
dev = [
|
|
24
|
+
"mypy>=1.15.0",
|
|
25
|
+
"pytest>=8.3.4",
|
|
26
|
+
"pytest-asyncio>=0.25.0",
|
|
27
|
+
"pytest-cov>=6.0.0",
|
|
28
|
+
"ruff>=0.8.4",
|
|
29
|
+
"taskiq-redis>=1.0.7",
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
[tool.pytest.ini_options]
|
|
33
|
+
asyncio_mode = "auto"
|
|
34
|
+
asyncio_default_fixture_loop_scope = "session"
|
|
35
|
+
testpaths = [
|
|
36
|
+
"tests"
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
[tool.ruff.lint]
|
|
40
|
+
ignore = [
|
|
41
|
+
"B006",
|
|
42
|
+
"B007",
|
|
43
|
+
"B009",
|
|
44
|
+
"B010",
|
|
45
|
+
"B026",
|
|
46
|
+
"B904",
|
|
47
|
+
"B905",
|
|
48
|
+
"C408",
|
|
49
|
+
"C901",
|
|
50
|
+
"E501",
|
|
51
|
+
"E714",
|
|
52
|
+
]
|
|
53
|
+
select = ["B", "C", "E", "F", "W", "I"]
|
|
54
|
+
|
|
55
|
+
[tool.ruff.format]
|
|
56
|
+
quote-style = "double"
|
|
57
|
+
indent-style = "space"
|
|
58
|
+
skip-magic-trailing-comma = false
|
|
59
|
+
line-ending = "auto"
|
|
60
|
+
docstring-code-format = false
|
|
61
|
+
docstring-code-line-length = "dynamic"
|
|
62
|
+
|
|
63
|
+
[tool.mypy]
|
|
64
|
+
python_version = "3.12"
|
|
65
|
+
pretty = true
|
|
66
|
+
ignore_missing_imports = true
|
|
67
|
+
check_untyped_defs = true
|
|
68
|
+
disallow_untyped_calls = true
|
|
69
|
+
disallow_untyped_defs = true
|
|
70
|
+
disallow_incomplete_defs = false
|
|
71
|
+
disallow_untyped_decorators = false
|
|
72
|
+
warn_redundant_casts = true
|
|
73
|
+
warn_unused_ignores = false
|
|
74
|
+
warn_return_any = false
|
|
75
|
+
warn_no_return = false
|
|
76
|
+
warn_unreachable = false
|
|
77
|
+
warn_unused_configs = true
|
|
78
|
+
allow_redefinition = true
|
|
79
|
+
strict_equality = true
|
|
80
|
+
show_error_context = true
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import typing as t
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
from pytest import Item
|
|
5
|
+
from pytest_asyncio import is_async_test
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
# dont need decorate test functions with pytest.mark.asyncio
|
|
9
|
+
def pytest_collection_modifyitems(items: t.List[Item]) -> None:
|
|
10
|
+
pytest_asyncio_tests = (item for item in items if is_async_test(item))
|
|
11
|
+
session_scope_marker = pytest.mark.asyncio(loop_scope="session")
|
|
12
|
+
for async_test in pytest_asyncio_tests:
|
|
13
|
+
async_test.add_marker(session_scope_marker, append=False)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
from unfazed.http import HttpRequest, JsonResponse
|
|
2
|
+
|
|
3
|
+
from .tasks import add
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
async def add_endpoint(request: HttpRequest, a: int, b: int) -> JsonResponse:
|
|
7
|
+
task = await add.kiq(a, b)
|
|
8
|
+
|
|
9
|
+
result = await task.wait_result(timeout=10)
|
|
10
|
+
|
|
11
|
+
return JsonResponse({"result": result.return_value})
|
|
File without changes
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
REDIS_HOST = os.getenv("REDIS_HOST", "redis")
|
|
4
|
+
|
|
5
|
+
UNFAZED_SETTINGS = {
|
|
6
|
+
"LIFESPAN": ["unfazed_taskiq.lifespan.TaskiqLifeSpan"],
|
|
7
|
+
"ROOT_URLCONF": "entry.routes",
|
|
8
|
+
"INSTALLED_APPS": ["app1"],
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
UNFAZED_TASKIQ_SETTINGS = {
|
|
13
|
+
"BROKER": {
|
|
14
|
+
"BACKEND": "taskiq.InMemoryBroker",
|
|
15
|
+
"OPTIONS": {},
|
|
16
|
+
},
|
|
17
|
+
"RESULT": {
|
|
18
|
+
"BACKEND": "taskiq_redis.RedisAsyncResultBackend",
|
|
19
|
+
"OPTIONS": {
|
|
20
|
+
"redis_url": f"redis://{REDIS_HOST}:6379",
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
"SCHEDULER": {
|
|
24
|
+
"BACKEND": "taskiq.scheduler.scheduler.TaskiqScheduler",
|
|
25
|
+
"SOURCES_CLS": ["taskiq.schedule_sources.LabelScheduleSource"],
|
|
26
|
+
},
|
|
27
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
UNFAZED_SETTINGS = {
|
|
2
|
+
"LIFESPAN": ["unfazed_taskiq.lifespan.TaskiqLifeSpan"],
|
|
3
|
+
"ROOT_URLCONF": "entry.routes",
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
UNFAZED_TASKIQ_SETTINGS = {
|
|
8
|
+
"BROKER": {
|
|
9
|
+
"BACKEND": "taskiq.InMemoryBroker",
|
|
10
|
+
"OPTIONS": {},
|
|
11
|
+
},
|
|
12
|
+
"RESULT": {
|
|
13
|
+
"BACKEND": "taskiq_redis.RedisAsyncResultBackend",
|
|
14
|
+
"OPTIONS": {
|
|
15
|
+
"redis_url": "redis://redis:6379",
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import os
|
|
3
|
+
import sys
|
|
4
|
+
import traceback
|
|
5
|
+
import warnings
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
async def main() -> None:
|
|
9
|
+
root_path = os.path.dirname(os.path.abspath(__file__))
|
|
10
|
+
sys.path.append(root_path)
|
|
11
|
+
os.environ.setdefault("UNFAZED_SETTINGS_MODULE", "entry.settings")
|
|
12
|
+
try:
|
|
13
|
+
from unfazed.core import Unfazed
|
|
14
|
+
except ImportError:
|
|
15
|
+
warnings.warn(
|
|
16
|
+
"Could not import unfazed. Did you forget to install it?", stacklevel=2
|
|
17
|
+
)
|
|
18
|
+
sys.exit(1)
|
|
19
|
+
|
|
20
|
+
try:
|
|
21
|
+
unfazed = Unfazed()
|
|
22
|
+
await unfazed.setup()
|
|
23
|
+
|
|
24
|
+
except Exception as e:
|
|
25
|
+
print(traceback.format_exc())
|
|
26
|
+
warnings.warn(f"An error occurred when init unfazed: {e}", stacklevel=2)
|
|
27
|
+
sys.exit(1)
|
|
28
|
+
|
|
29
|
+
await unfazed.execute_command_from_argv()
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
if __name__ == "__main__":
|
|
33
|
+
asyncio.run(main())
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
import typing as t
|
|
4
|
+
|
|
5
|
+
import pytest
|
|
6
|
+
from unfazed.core import Unfazed
|
|
7
|
+
from unfazed.test import Requestfactory
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@pytest.fixture
|
|
11
|
+
async def unfazed() -> t.AsyncGenerator[Unfazed, None]:
|
|
12
|
+
os.environ["UNFAZED_SETTINGS_MODULE"] = "tests.proj.entry.settings"
|
|
13
|
+
|
|
14
|
+
path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "../proj")
|
|
15
|
+
|
|
16
|
+
sys.path.append(path)
|
|
17
|
+
|
|
18
|
+
unfazed = Unfazed()
|
|
19
|
+
await unfazed.setup()
|
|
20
|
+
|
|
21
|
+
yield unfazed
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
async def test_api(unfazed: Unfazed) -> None:
|
|
25
|
+
async with Requestfactory(unfazed) as rf:
|
|
26
|
+
resp = await rf.get("/app1/add?a=1&b=2")
|
|
27
|
+
|
|
28
|
+
assert resp.status_code == 200
|
|
29
|
+
assert resp.json() == {"result": 3}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
from taskiq import InMemoryBroker
|
|
4
|
+
from taskiq.scheduler.scheduler import TaskiqScheduler
|
|
5
|
+
from taskiq_redis import RedisAsyncResultBackend
|
|
6
|
+
|
|
7
|
+
from unfazed_taskiq import TaskiqAgent
|
|
8
|
+
from unfazed_taskiq.settings import UnfazedTaskiqSettings
|
|
9
|
+
|
|
10
|
+
REDIS_HOST = os.getenv("REDIS_HOST", "redis")
|
|
11
|
+
|
|
12
|
+
TEMP_SETTINGS = {
|
|
13
|
+
"BROKER": {
|
|
14
|
+
"BACKEND": "taskiq.InMemoryBroker",
|
|
15
|
+
"OPTIONS": {},
|
|
16
|
+
},
|
|
17
|
+
"RESULT": {
|
|
18
|
+
"BACKEND": "taskiq_redis.RedisAsyncResultBackend",
|
|
19
|
+
"OPTIONS": {
|
|
20
|
+
"redis_url": f"redis://{REDIS_HOST}:6379",
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
"SCHEDULER": {
|
|
24
|
+
"BACKEND": "taskiq.scheduler.scheduler.TaskiqScheduler",
|
|
25
|
+
"SOURCES_CLS": ["taskiq.schedule_sources.LabelScheduleSource"],
|
|
26
|
+
},
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
async def test_agent() -> None:
|
|
31
|
+
agent = TaskiqAgent()
|
|
32
|
+
|
|
33
|
+
settings = UnfazedTaskiqSettings.model_validate(TEMP_SETTINGS)
|
|
34
|
+
agent.setup(settings)
|
|
35
|
+
|
|
36
|
+
assert isinstance(agent.broker, InMemoryBroker)
|
|
37
|
+
assert isinstance(agent.broker.result_backend, RedisAsyncResultBackend)
|
|
38
|
+
assert isinstance(agent.scheduler, TaskiqScheduler)
|
|
39
|
+
|
|
40
|
+
await agent.startup()
|
|
41
|
+
|
|
42
|
+
await agent.shutdown()
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import typing as t
|
|
3
|
+
|
|
4
|
+
import pytest
|
|
5
|
+
from taskiq import InMemoryBroker
|
|
6
|
+
from taskiq.scheduler.scheduler import TaskiqScheduler
|
|
7
|
+
from taskiq_redis import RedisAsyncResultBackend
|
|
8
|
+
|
|
9
|
+
from unfazed_taskiq.cli import get_agent
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@pytest.fixture
|
|
13
|
+
def setup_cli() -> t.Generator[None, None, None]:
|
|
14
|
+
os.environ["UNFAZED_SETTINGS_MODULE"] = "tests.proj.entry.settings"
|
|
15
|
+
|
|
16
|
+
yield
|
|
17
|
+
|
|
18
|
+
del os.environ["UNFAZED_SETTINGS_MODULE"]
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@pytest.fixture
|
|
22
|
+
def setup_cli2() -> t.Generator[None, None, None]:
|
|
23
|
+
os.environ["UNFAZED_SETTINGS_MODULE"] = "tests.proj.entry2.settings"
|
|
24
|
+
|
|
25
|
+
yield
|
|
26
|
+
|
|
27
|
+
del os.environ["UNFAZED_SETTINGS_MODULE"]
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def test_cli(setup_cli: t.Generator[None, None, None]) -> None:
|
|
31
|
+
agent = get_agent()
|
|
32
|
+
|
|
33
|
+
assert isinstance(agent.broker, InMemoryBroker)
|
|
34
|
+
assert isinstance(agent.broker.result_backend, RedisAsyncResultBackend)
|
|
35
|
+
assert isinstance(agent.scheduler, TaskiqScheduler)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def test_cli_without_env() -> None:
|
|
39
|
+
if "UNFAZED_SETTINGS_MODULE" in os.environ:
|
|
40
|
+
del os.environ["UNFAZED_SETTINGS_MODULE"]
|
|
41
|
+
|
|
42
|
+
with pytest.raises(ValueError):
|
|
43
|
+
get_agent()
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def test_cli_without_scheduler(setup_cli2: t.Generator[None, None, None]) -> None:
|
|
47
|
+
agent = get_agent()
|
|
48
|
+
|
|
49
|
+
assert isinstance(agent.broker, InMemoryBroker)
|
|
50
|
+
assert isinstance(agent.broker.result_backend, RedisAsyncResultBackend)
|
|
51
|
+
assert agent.scheduler is None
|