Skip to content

Commit

Permalink
Schedule daily tasks to occur at midnight
Browse files Browse the repository at this point in the history
TODO: Have this configurable in the .env, but for now it's set to hour 0
  • Loading branch information
Grygon committed Sep 9, 2023
1 parent 2f555f7 commit 3d36cfd
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 9 deletions.
9 changes: 6 additions & 3 deletions mealie/repos/repository_meals.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from datetime import date
from datetime import date, timedelta
from uuid import UUID

from sqlalchemy import select
Expand All @@ -14,7 +14,10 @@ def by_group(self, group_id: UUID) -> "RepositoryMeals":
return super().by_group(group_id)

def get_today(self, group_id: UUID) -> list[ReadPlanEntry]:
today = date.today()
stmt = select(GroupMealPlan).filter(GroupMealPlan.date == today, GroupMealPlan.group_id == group_id)
return self.get_for_day(group_id, 0)

def get_for_day(self, group_id: UUID, relative_day: int) -> list[ReadPlanEntry]:
day = date.today() + timedelta(days=relative_day)
stmt = select(GroupMealPlan).filter(GroupMealPlan.date == day, GroupMealPlan.group_id == group_id)
plans = self.session.execute(stmt).scalars().all()
return [self.schema.from_orm(x) for x in plans]
25 changes: 23 additions & 2 deletions mealie/services/scheduler/scheduler_service.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import asyncio
from datetime import datetime, timedelta

from pathlib import Path

from mealie.core import root_logger
Expand All @@ -18,9 +21,27 @@ class SchedulerService:
@staticmethod
async def start():
await run_minutely()
await run_daily()
await run_hourly()

# Wait to trigger our daily run until our given "daily time", so having asyncio handle it.
asyncio.create_task(schedule_daily())


async def schedule_daily():
target_time = time_at_hour(0)
logger.debug("Daily tasks scheduled for " + str(target_time))
wait_seconds = (target_time - datetime.now()).total_seconds()
await asyncio.sleep(wait_seconds)
await run_daily()


def time_at_hour(hour=0):
"""Return a time for the next occurence of the given hour for the local time zone."""
now = datetime.now()
hours_until = ((hour - now.hour) % 24) or 24
dt = timedelta(hours=hours_until)
return (now + dt).replace(microsecond=0, second=0, minute=0)


def _scheduled_task_wrapper(callable):
try:
Expand All @@ -29,7 +50,7 @@ def _scheduled_task_wrapper(callable):
logger.error(f"Error in scheduled task func='{callable.__name__}': exception='{e}'")


@repeat_every(minutes=MINUTES_DAY, wait_first=True, logger=logger)
@repeat_every(minutes=MINUTES_DAY, wait_first=False, logger=logger)
def run_daily():
logger.debug("Running daily callbacks")
for func in SchedulerRegistry._daily:
Expand Down
9 changes: 5 additions & 4 deletions mealie/services/scheduler/tasks/create_timeline_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@


def create_mealplan_timeline_events(group_id: UUID4 | None = None):
event_time = datetime.now(timezone.utc)
# Move it back by 1 minute to ensure that midnight processing logs it to the prev day
event_time = datetime.now(timezone.utc) - timedelta(minutes=1)

with session_context() as session:
repos = get_repositories(session)
Expand All @@ -38,7 +39,7 @@ def create_mealplan_timeline_events(group_id: UUID4 | None = None):
recipes_to_update: dict[UUID4, RecipeSummary] = {}
recipe_id_to_slug_map: dict[UUID4, str] = {}

mealplans = repos.meals.get_today(group_id)
mealplans = repos.meals.get_for_day(group_id, -1)
for mealplan in mealplans:
if not (mealplan.recipe and mealplan.user_id):
continue
Expand All @@ -54,8 +55,8 @@ def create_mealplan_timeline_events(group_id: UUID4 | None = None):
else:
event_subject = f"{user.full_name} made this for {mealplan.entry_type.value}"

query_start_time = datetime.combine(datetime.now(timezone.utc).date(), time.min)
query_end_time = query_start_time + timedelta(days=1)
query_end_time = datetime.now() - timedelta()
query_start_time = query_end_time - timedelta(days=1, minutes=1, seconds=5)
query = PaginationQuery(
query_filter=(
f'recipe_id = "{mealplan.recipe_id}" '
Expand Down

0 comments on commit 3d36cfd

Please sign in to comment.