8000 - added celery task for generating .xlsx menu · mr-st0rm/CafeMenuApp_RESTAPI@6da428b · GitHub
[go: up one dir, main page]

Skip to content

Commit 6da428b

Browse files
committed
- added celery task for generating .xlsx menu
1 parent c36096e commit 6da428b

20 files changed

+333
-7
lines changed

.prod.env

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,6 @@ POSTGRES_DB=menu_app
1111
RS_HOST=redis-db
1212
RS_PORT=6379
1313
RS_DB=0
14+
15+
C_BROKER_URL=amqp://guest:guest@rabbit-mq:5672//
16+
C_RESULT_BACKEND=rpc://

.test.env

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,7 @@ POSTGRES_DB=test_menu_app
1010
RS_HOST=test-redis
1111
RS_PORT=6379
1212
RS_DB=1
13+
14+
15+
C_BROKER_URL=amqp://guest:guest@rabbit:5672//
16+
C_RESULT_BACKEND=rpc://

app/api/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from .v1.routes.fill_db_routers import db_fill_router
66
from .v1.routes.menu_routes import menu_router
77
from .v1.routes.submenu_router import submenu_router
8+
from .v1.routes.xls_generator_routers import xlsx_generator_router
89

910

1011
def register_api_routes(app: FastAPI):
@@ -18,3 +19,4 @@ def register_api_routes(app: FastAPI):
1819
app.include_router(submenu_router, prefix="/api/v1")
1920
app.include_router(dish_router, prefix="/api/v1")
2021
app.include_router(db_fill_router, prefix="/api/v1")
22+
app.include_router(xlsx_generator_router, prefix="/api/v1")

app/api/v1/docs/menu_methods_description.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,8 @@ class DishApiDocs:
3030

3131
class FillDatabaseDocs:
3232
POST_FILL = "Fill database with any records"
33+
34+
35+
class ReportGenerators:
36+
POST_XLSX = "Create task in celery for generating .xlsx report"
37+
GET_XLSX = "Get detailed information about task"
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
from fastapi import APIRouter, Depends, status
2+
3+
from app.api.v1.docs.menu_methods_description import ReportGenerators
4+
from app.api.v1.schemas import response as res_model
5+
from app.celery.tasks import create_report_xlsx
6+
from app.services.service import Services, service_stub
7+
8+
xlsx_generator_router = APIRouter(prefix="/report")
9+
10+
11+
@xlsx_generator_router.post(
12+
"/xlsx",
13+
tags=["Report generators"],
14+
description=ReportGenerators.POST_XLSX,
15+
summary=ReportGenerators.POST_XLSX,
16+
status_code=status.HTTP_202_ACCEPTED,
17+
response_model=res_model.CreatedTask,
18+
)
19+
async def create_task_for_generate_xlsx(
20+
services: Services = Depends(service_stub),
21+
):
22+
"""
23+
Create task in celery for generating a .xlsx file of menu
24+
25+
:param services: Services for application
26+
:return: created task id
27+
"""
28+
menus = await services.report_generator_service.get_all_data()
29+
task = create_report_xlsx.apply_async(args=[menus])
30+
31+
return res_model.CreatedTask(task_id=task.id)
32+
33+
34+
@xlsx_generator_router.get(
35+
"/xlsx/{task_id}",
36+
tags=["Report generators"],
37+
description=ReportGenerators.GET_XLSX,
38+
summary=ReportGenerators.GET_XLSX,
39+
response_model=res_model.DetailedTask,
40+
)
41+
async def get_status_of_task_xlsx(
42+
task_id: str, services: Services = Depends(service_stub)
43+
):
44+
"""
45+
Get detailed info about task
46+
47+
:param services: Services for application
48+
:param task_id: target task id
49+
:return: detailed info about task
50+
"""
51+
task = services.tasks_service.get_task(task_id)
52+
53+
return task

app/api/v1/schemas/response.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,12 @@ class Dish(BaseMenu):
3131
"""Response model of Dish"""
3232

3333
price: str
34+
35+
36+
class CreatedTask(BaseModel):
37+
task_id: str
38+
39+
40+
class DetailedTask(CreatedTask):
41+
status: str
42+
result: str | None

app/celery/__init__.py

Whitespace-only changes.

app/celery/celery_app.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
from celery import Celery
2+
3+
from app.config.cfg import load_config
4+
5+
6+
def route_task(name, args, kwargs, options, task=None, **kw):
7+
if ":" in name:
8+
_, queue = name.split(":")
9+
return {"queue": queue}
10+
11+
return {"queue": "celery"}
12+
13+
14+
celery = Celery(
15+
__name__,
16+
include=["app.celery.tasks"],
17+
)
18+
celery.config_from_object(load_config().celery)
19+
celery.conf.task_default_queue = "celery"
20+
celery.conf.task_routes = (route_task,)
21+
celery.autodiscover_tasks()

app/celery/tasks.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import uuid
2+
3+
import xlsxwriter
4+
5+
from app.services.db_fill.database_fill_models import Menu
6+
7+
from .celery_app import celery
8+
9+
10+
@celery.task(name="app.create_report_xlsx:celery")
11+
def create_report_xlsx(menus_list: list[dict]):
12+
name = f"reports/{uuid.uuid4().hex}.xlsx"
13+
generate_xlsx(name, menus_list)
14+
15+
return name
16+
17+
18+
def generate_xlsx(name: str, menus: list[dict]):
19+
"""
20+
Generate xlsx file for menu
21+
22+
:param name: filename
23+
:param menus: list of menus
24+
"""
25+
with xlsxwriter.Workbook(name) as book:
26+
book_sheet = book.add_worksheet("Menu")
27+
column = 0
28+
row = 0
29+
30+
for i, menu in enumerate(menus):
31+
menu = Menu(**menu)
32+
33+
book_sheet.write(row, column, menu.title)
34+
book_sheet.write(row, column + 1, menu.description)
35+
36+
column += 2
37+
row += 1
38+
39+
for submenu in menu.submenus:
40+
book_sheet.write(row, column, submenu.title)
41+
book_sheet.write(row, column + 1, submenu.description)
42+
43+
row += 1
44+
column += 2
45+
46+
for dish in submenu.dishes:
47+
book_sheet.write(row, column, dish.title)
48+
book_sheet.write(row, column + 1, dish.description)
49+
book_sheet.write(row, column + 2, dish.price)
50+
51+
row += 1
52+
53+
column -= 2
54+
55+
column = 0
56+
row += 2

app/config/cfg.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,18 @@ class RedisCache:
3131
db_id: int
3232

3333

34+
@dataclass
35+
class CeleryApp:
36+
broker_url: str
37+
result_backend: str
38+
39+
3440
@dataclass
3541
class AppConfig:
3642
app: FastApiApp
3743
db: DataBase
3844
redis: RedisCache
45+
celery: CeleryApp
3946

4047

4148
def load_config(cfg_path: str = ".prod.env") -> AppConfig:
@@ -66,4 +73,8 @@ def load_config(cfg_path: str = ".prod.env") -> AppConfig:
6673
port=env.int("RS_PORT"),
6774
db_id=env.int("RS_DB"),
6875
),
76+
celery=CeleryApp(
77+
broker_url=env.str("C_BROKER_URL"),
78+
result_backend=env.str("C_RESULT_BACKEND"),
79+
),
6980
)

0 commit comments

Comments
 (0)
0