Skip to content

Commit 31cfb0b

Browse files
authored
Merge pull request #12 from sumaro2101/develop
Develop
2 parents 54834a1 + 88b3aba commit 31cfb0b

8 files changed

Lines changed: 100 additions & 18 deletions

File tree

api_v1/tests/conftest.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import sys
21
import asyncio
32
import httpx
43
import pytest_asyncio
@@ -39,7 +38,6 @@ async def app() -> AsyncGenerator[LifespanManager, Any]:
3938
async def lifespan(app: FastAPI):
4039
async with db_setup.engine.begin() as conn:
4140
await conn.run_sync(BaseModel.metadata.create_all)
42-
sys.stdout.write('alembic upgrade head')
4341
yield
4442
await conn.run_sync(BaseModel.metadata.drop_all)
4543

@@ -63,3 +61,9 @@ async def client(app: FastAPI) -> AsyncGenerator[httpx.AsyncClient, Any]:
6361
base_url=current_home + current_api,
6462
) as client:
6563
yield client
64+
65+
66+
@pytest_asyncio.fixture()
67+
async def get_async_session():
68+
async with db_setup.session() as session:
69+
yield session

api_v1/users/tasks.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from config import celery_app
1+
from config import celery_app, settings
22
import asyncio
33

44

@@ -9,3 +9,12 @@ async def time_sleep_task():
99
"""
1010
await asyncio.sleep(2.0)
1111
return 'Task is done'
12+
13+
14+
celery_app.conf.beat_schedule = {
15+
'test-every-10-seconds': {
16+
'task': 'llm_analizer.tasks.test',
17+
'schedule': settings.celery.TEST_TIMEDELTA,
18+
'args': ('hello',)
19+
},
20+
}

async_alembic/env.py

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33

44
from sqlalchemy import pool
55
from sqlalchemy.engine import Connection
6-
from sqlalchemy.ext.asyncio import async_engine_from_config
6+
from sqlalchemy.ext.asyncio import async_engine_from_config, AsyncEngine
7+
from sqlalchemy import engine_from_config
78

89
from alembic import context
910

@@ -58,34 +59,43 @@ def run_migrations_offline() -> None:
5859

5960

6061
def do_run_migrations(connection: Connection) -> None:
61-
context.configure(connection=connection, target_metadata=target_metadata)
62-
62+
context.configure(
63+
connection=connection,
64+
target_metadata=target_metadata,
65+
compare_type=True,
66+
)
6367
with context.begin_transaction():
6468
context.run_migrations()
6569

6670

67-
async def run_async_migrations() -> None:
71+
async def run_async_migrations(connectable) -> None:
6872
"""In this scenario we need to create an Engine
6973
and associate a connection with the context.
7074
7175
"""
72-
73-
connectable = async_engine_from_config(
74-
config.get_section(config.config_ini_section, {}),
75-
prefix="sqlalchemy.",
76-
poolclass=pool.NullPool,
77-
)
78-
7976
async with connectable.connect() as connection:
8077
await connection.run_sync(do_run_migrations)
81-
8278
await connectable.dispose()
8379

8480

8581
def run_migrations_online() -> None:
8682
"""Run migrations in 'online' mode."""
87-
88-
asyncio.run(run_async_migrations())
83+
connectable = context.config.attributes.get('connection', None)
84+
if connectable is None:
85+
connectable = AsyncEngine(
86+
engine_from_config(
87+
context.config.get_section(
88+
context.config.config_ini_section,
89+
),
90+
prefix='sqlalchemy.',
91+
poolclass=pool.NullPool,
92+
future=True,
93+
)
94+
)
95+
if isinstance(connectable, AsyncEngine):
96+
asyncio.run(run_async_migrations(connectable))
97+
else:
98+
do_run_migrations(connectable)
8999

90100

91101
if context.is_offline_mode():

config/celery/connection.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,8 @@ def wrapper(*args,
4141

4242
app = Celery(__name__)
4343
app.conf.broker_url = settings.rabbit.broker_url
44+
app.conf.result_backend = 'db+' + settings.db.url
45+
app.conf.database_engine_options = {'echo': True}
46+
app.conf.timezone = settings.celery.TIMEZONE
47+
app.conf.broker_connection_retry_on_startup = True
4448
app.autodiscover_tasks(packages=['api_v1.users'])

config/config.py

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
from pathlib import Path
22
from pydantic_settings import BaseSettings, SettingsConfigDict
3-
from pydantic import BaseModel
3+
from pydantic import BaseModel, ConfigDict
44
from starlette.config import Config
5+
from celery.schedules import crontab
56

67

78
base_dir = Path(__file__).resolve().parent.parent
@@ -11,6 +12,14 @@
1112
config = Config('.env')
1213

1314

15+
class AlembicSettings(BaseModel):
16+
"""
17+
Настройки Alembic
18+
"""
19+
CONFIG_PATH: Path = Path('alembic.ini')
20+
MIGRATION_PATH: Path = Path('async_alembic/')
21+
22+
1423
class TestDBSettings(BaseModel):
1524
"""
1625
Настройки тестовой базы данных
@@ -35,6 +44,23 @@ class DBSettings(BaseModel):
3544
url: str = f'{_engine}://{_owner}:{_password}@{_name}/{_db_name}'
3645

3746

47+
class CelerySettings(BaseModel):
48+
"""
49+
Настройки Celery
50+
"""
51+
model_config = ConfigDict(
52+
arbitrary_types_allowed=True,
53+
)
54+
TIMEZONE: str = 'Europe/Moscow'
55+
TIMEDELTA_PER_DAY: crontab = crontab(minute=0,
56+
hour=2,
57+
day_of_week='*/1',
58+
day_of_month='*/1',
59+
month_of_year='*/1',
60+
)
61+
TEST_TIMEDELTA: crontab = crontab(minute='*/1')
62+
63+
3864
class RabbitSettings(BaseModel):
3965
"""
4066
Настройки RabbitMQ
@@ -62,7 +88,9 @@ class Settings(BaseSettings):
6288
)
6389
db: DBSettings = DBSettings()
6490
test_db: TestDBSettings = TestDBSettings()
91+
celery: CelerySettings = CelerySettings()
6592
rabbit: RabbitSettings = RabbitSettings()
93+
alembic: AlembicSettings = AlembicSettings()
6694
debug: bool = bool(int(config('DEBUG')))
6795
API_PREFIX: str = '/api/v1'
6896
BASE_DIR: Path = base_dir

docker-compose.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,20 @@ services:
4242
- db
4343
- fast_api
4444

45+
celery_beat:
46+
build:
47+
context: .
48+
dockerfile: ./docker/fastapi/Dockerfile
49+
command: /start-celerybeat
50+
volumes:
51+
- .:/app
52+
env_file:
53+
- .env
54+
depends_on:
55+
- rabbitmq
56+
- db
57+
- fast_api
58+
4559
dashboard:
4660
build:
4761
context: .

docker/celery/beat/start

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#!/bin/bash
2+
3+
set -o errexit
4+
set -o nounset
5+
6+
celery -A config.celery.connection.app \
7+
--broker=amqp://"${RABBITMQ_DEFAULT_USER}":"${RABBITMQ_DEFAULT_PASS}"@"${RMQ_HOST}":"${RMQ_PORT}" \
8+
beat \
9+
--loglevel=info

docker/fastapi/Dockerfile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ COPY ./docker/celery/worker/start /start-celeryworker
3737
RUN sed -i 's/\r$//g' /start-celeryworker
3838
RUN chmod +x /start-celeryworker
3939

40+
COPY ./docker/celery/beat/start /start-celerybeat
41+
RUN sed -i 's/\r$//g' /start-celerybeat
42+
RUN chmod +x /start-celerybeat
43+
4044
COPY ./docker/celery/flower/start /start-flower
4145
RUN sed -i 's/\r$//g' /start-flower
4246
RUN chmod +x /start-flower

0 commit comments

Comments
 (0)