mirror of
https://github.com/mealie-recipes/mealie.git
synced 2026-02-11 18:33:11 -05:00
refactor: webhook events (#1661)
* refactored EventBusService to work outside FastAPI * extended event models * refactored webhooks to run through event bus * added basic webhook test route * changed get_all to page_all * fixed incorrectly implemented Vue variables * fixed broken webhook test * changed factory from staticmethod to classmethod * made query boundary definitions easier to read
This commit is contained in:
@@ -1,54 +1,63 @@
|
||||
from datetime import datetime, timezone
|
||||
from typing import Optional
|
||||
|
||||
import requests
|
||||
from fastapi.encoders import jsonable_encoder
|
||||
from pydantic import UUID4
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from mealie.db.db_setup import create_session
|
||||
from mealie.db.models.group.webhooks import GroupWebhooksModel
|
||||
from mealie.repos.all_repositories import get_repositories
|
||||
from mealie.schema.response.pagination import PaginationQuery
|
||||
from mealie.services.event_bus_service.event_bus_service import EventBusService
|
||||
from mealie.services.event_bus_service.event_types import (
|
||||
INTERNAL_INTEGRATION_ID,
|
||||
EventDocumentType,
|
||||
EventOperation,
|
||||
EventTypes,
|
||||
EventWebhookData,
|
||||
)
|
||||
|
||||
last_ran = datetime.now(timezone.utc)
|
||||
|
||||
|
||||
def get_scheduled_webhooks(session: Session, bottom: datetime, top: datetime) -> list[GroupWebhooksModel]:
|
||||
def post_group_webhooks(start_dt: Optional[datetime] = None, group_id: Optional[UUID4] = None) -> None:
|
||||
"""Post webhook events to specified group, or all groups"""
|
||||
|
||||
global last_ran
|
||||
|
||||
# if not specified, start the query at the last time the service ran
|
||||
start_dt = start_dt or last_ran
|
||||
|
||||
# end the query at the current time
|
||||
last_ran = end_dt = datetime.now(timezone.utc)
|
||||
|
||||
if group_id is None:
|
||||
# publish the webhook event to each group's event bus
|
||||
session = create_session()
|
||||
repos = get_repositories(session)
|
||||
groups_data = repos.groups.page_all(PaginationQuery(page=1, per_page=-1))
|
||||
group_ids = [group.id for group in groups_data.items]
|
||||
|
||||
else:
|
||||
group_ids = [group_id]
|
||||
|
||||
"""
|
||||
get_scheduled_webhooks queries the database for all webhooks scheduled between the bottom and
|
||||
top time ranges. It returns a list of GroupWebhooksModel objects.
|
||||
At this time only mealplan webhooks are supported. To add support for more types,
|
||||
add a dispatch event for that type here (e.g. EventDocumentType.recipe_bulk_report) and
|
||||
handle the webhook data in the webhook event bus listener
|
||||
"""
|
||||
|
||||
return (
|
||||
session.query(GroupWebhooksModel)
|
||||
.where(
|
||||
GroupWebhooksModel.enabled == True, # noqa: E712 - required for SQLAlchemy comparison
|
||||
GroupWebhooksModel.scheduled_time > bottom.astimezone(timezone.utc).time(),
|
||||
GroupWebhooksModel.scheduled_time <= top.astimezone(timezone.utc).time(),
|
||||
)
|
||||
.all()
|
||||
event_type = EventTypes.webhook_task
|
||||
event_document_data = EventWebhookData(
|
||||
document_type=EventDocumentType.mealplan,
|
||||
operation=EventOperation.info,
|
||||
webhook_start_dt=start_dt,
|
||||
webhook_end_dt=end_dt,
|
||||
)
|
||||
|
||||
|
||||
def post_group_webhooks() -> None:
|
||||
global last_ran
|
||||
session = create_session()
|
||||
results = get_scheduled_webhooks(session, last_ran, datetime.now())
|
||||
|
||||
last_ran = datetime.now(timezone.utc)
|
||||
|
||||
repos = get_repositories(session)
|
||||
|
||||
memo = {}
|
||||
|
||||
def get_meals(group_id: UUID4):
|
||||
if group_id not in memo:
|
||||
memo[group_id] = repos.meals.get_all(group_id=group_id)
|
||||
return memo[group_id]
|
||||
|
||||
for result in results:
|
||||
meals = get_meals(result.group_id)
|
||||
|
||||
if not meals:
|
||||
continue
|
||||
|
||||
requests.post(result.url, json=jsonable_encoder(meals))
|
||||
for group_id in group_ids:
|
||||
event_bus = EventBusService(group_id=group_id)
|
||||
event_bus.dispatch(
|
||||
integration_id=INTERNAL_INTEGRATION_ID,
|
||||
group_id=group_id,
|
||||
event_type=event_type,
|
||||
document_data=event_document_data,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user