mirror of
https://github.com/hay-kot/mealie.git
synced 2025-08-22 14:33:33 -07:00
fixed broken scheduler
This commit is contained in:
parent
2ad4085c9d
commit
6bc533cf70
11 changed files with 113 additions and 94 deletions
|
@ -12,7 +12,7 @@
|
||||||
</v-col>
|
</v-col>
|
||||||
<v-spacer></v-spacer>
|
<v-spacer></v-spacer>
|
||||||
<v-col align="end">
|
<v-col align="end">
|
||||||
<v-menu offset-y>
|
<v-menu offset-y v-if="sortable">
|
||||||
<template v-slot:activator="{ on, attrs }">
|
<template v-slot:activator="{ on, attrs }">
|
||||||
<v-btn-toggle group>
|
<v-btn-toggle group>
|
||||||
<v-btn text v-bind="attrs" v-on="on"> Sort </v-btn>
|
<v-btn text v-bind="attrs" v-on="on"> Sort </v-btn>
|
||||||
|
@ -59,6 +59,9 @@ export default {
|
||||||
RecipeCard,
|
RecipeCard,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
|
sortable: {
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
title: String,
|
title: String,
|
||||||
recipes: Array,
|
recipes: Array,
|
||||||
cardLimit: {
|
cardLimit: {
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
:card-limit="pageSettings.showLimit"
|
:card-limit="pageSettings.showLimit"
|
||||||
/>
|
/>
|
||||||
<CardSection
|
<CardSection
|
||||||
|
:sortable="true"
|
||||||
v-for="(section, index) in recipeByCategory"
|
v-for="(section, index) in recipeByCategory"
|
||||||
:key="index"
|
:key="index"
|
||||||
:title="section.title"
|
:title="section.title"
|
||||||
|
@ -54,13 +55,11 @@ export default {
|
||||||
this.recipeByCategory[index].recipes.sort((a, b) =>
|
this.recipeByCategory[index].recipes.sort((a, b) =>
|
||||||
a.name > b.name ? 1 : -1
|
a.name > b.name ? 1 : -1
|
||||||
);
|
);
|
||||||
console.log(this.recipeByCategory[index].recipes);
|
|
||||||
},
|
},
|
||||||
sortRecent(index) {
|
sortRecent(index) {
|
||||||
this.recipeByCategory[index].recipes.sort((a, b) =>
|
this.recipeByCategory[index].recipes.sort((a, b) =>
|
||||||
a.dateAdded > b.dateAdded ? -1 : 1
|
a.dateAdded > b.dateAdded ? -1 : 1
|
||||||
);
|
);
|
||||||
console.log(this.recipeByCategory[index].recipes);
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -14,7 +14,7 @@ from routes import (
|
||||||
user_routes,
|
user_routes,
|
||||||
)
|
)
|
||||||
|
|
||||||
# from utils.api_docs import generate_api_docs
|
from utils.api_docs import generate_api_docs
|
||||||
from utils.logger import logger
|
from utils.logger import logger
|
||||||
|
|
||||||
app = FastAPI(
|
app = FastAPI(
|
||||||
|
@ -46,6 +46,11 @@ if PRODUCTION:
|
||||||
|
|
||||||
api_routers()
|
api_routers()
|
||||||
|
|
||||||
|
|
||||||
|
def start_scheduler():
|
||||||
|
import services.scheduler.scheduled_jobs
|
||||||
|
|
||||||
|
|
||||||
# API 404 Catch all CALL AFTER ROUTERS
|
# API 404 Catch all CALL AFTER ROUTERS
|
||||||
@app.get("/api/{full_path:path}", status_code=404, include_in_schema=False)
|
@app.get("/api/{full_path:path}", status_code=404, include_in_schema=False)
|
||||||
def invalid_api():
|
def invalid_api():
|
||||||
|
@ -56,8 +61,10 @@ app.include_router(static_routes.router)
|
||||||
|
|
||||||
|
|
||||||
# Generate API Documentation
|
# Generate API Documentation
|
||||||
# if not PRODUCTION:
|
if not PRODUCTION:
|
||||||
# generate_api_docs(app)
|
generate_api_docs(app)
|
||||||
|
|
||||||
|
start_scheduler()
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
logger.info("-----SYSTEM STARTUP-----")
|
logger.info("-----SYSTEM STARTUP-----")
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
from db.db_setup import generate_session
|
from db.db_setup import generate_session
|
||||||
from fastapi import APIRouter, Depends, HTTPException
|
from fastapi import APIRouter, Depends, HTTPException
|
||||||
from services.scheduler_services import post_webhooks
|
|
||||||
from services.settings_services import SiteSettings, SiteTheme
|
from services.settings_services import SiteSettings, SiteTheme
|
||||||
from sqlalchemy.orm.session import Session
|
from sqlalchemy.orm.session import Session
|
||||||
from utils.global_scheduler import scheduler
|
from utils.post_webhooks import post_webhooks
|
||||||
from utils.snackbar import SnackResponse
|
from utils.snackbar import SnackResponse
|
||||||
|
|
||||||
router = APIRouter(tags=["Settings"])
|
router = APIRouter(tags=["Settings"])
|
||||||
|
@ -34,7 +33,6 @@ def update_settings(data: SiteSettings, db: Session = Depends(generate_session))
|
||||||
# status_code=400, detail=SnackResponse.error("Unable to Save Settings")
|
# status_code=400, detail=SnackResponse.error("Unable to Save Settings")
|
||||||
# )
|
# )
|
||||||
|
|
||||||
# scheduler.reschedule_webhooks() #! Need to fix Scheduler
|
|
||||||
return SnackResponse.success("Settings Updated")
|
return SnackResponse.success("Settings Updated")
|
||||||
|
|
||||||
|
|
||||||
|
|
3
mealie/services/scheduler/global_scheduler.py
Normal file
3
mealie/services/scheduler/global_scheduler.py
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
from apscheduler.schedulers.background import BackgroundScheduler
|
||||||
|
|
||||||
|
scheduler = BackgroundScheduler()
|
62
mealie/services/scheduler/scheduled_jobs.py
Normal file
62
mealie/services/scheduler/scheduled_jobs.py
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
from apscheduler.schedulers.background import BackgroundScheduler
|
||||||
|
from db.db_setup import create_session
|
||||||
|
from services.backups.exports import auto_backup_job
|
||||||
|
from services.scheduler.global_scheduler import scheduler
|
||||||
|
from services.scheduler.scheduler_utils import Cron, cron_parser
|
||||||
|
from services.settings_services import SiteSettings
|
||||||
|
from utils.logger import logger
|
||||||
|
from utils.post_webhooks import post_webhooks
|
||||||
|
|
||||||
|
|
||||||
|
@scheduler.scheduled_job(trigger="interval", minutes=15)
|
||||||
|
def update_webhook_schedule():
|
||||||
|
"""
|
||||||
|
A scheduled background job that runs every 15 minutes to
|
||||||
|
poll the database for changes and reschedule the webhook time
|
||||||
|
"""
|
||||||
|
session = create_session()
|
||||||
|
settings = SiteSettings.get_site_settings(session=session)
|
||||||
|
time = cron_parser(settings.webhooks.webhookTime)
|
||||||
|
job = JOB_STORE.get("webhooks")
|
||||||
|
|
||||||
|
scheduler.reschedule_job(
|
||||||
|
job.scheduled_task.id,
|
||||||
|
trigger="cron",
|
||||||
|
hour=time.hours,
|
||||||
|
minute=time.minutes,
|
||||||
|
)
|
||||||
|
|
||||||
|
session.close()
|
||||||
|
logger.info(scheduler.print_jobs())
|
||||||
|
|
||||||
|
|
||||||
|
class ScheduledFunction:
|
||||||
|
def __init__(
|
||||||
|
self, scheduler: BackgroundScheduler, function, cron: Cron, name: str
|
||||||
|
) -> None:
|
||||||
|
self.scheduled_task = scheduler.add_job(
|
||||||
|
function,
|
||||||
|
trigger="cron",
|
||||||
|
name=name,
|
||||||
|
hour=cron.hours,
|
||||||
|
minute=cron.minutes,
|
||||||
|
max_instances=1,
|
||||||
|
replace_existing=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
logger.info("New Function Scheduled")
|
||||||
|
logger.info(scheduler.print_jobs())
|
||||||
|
|
||||||
|
|
||||||
|
logger.info("----INIT SCHEDULE OBJECT-----")
|
||||||
|
|
||||||
|
JOB_STORE = {
|
||||||
|
"backup_job": ScheduledFunction(
|
||||||
|
scheduler, auto_backup_job, Cron(hours=00, minutes=00), "backups"
|
||||||
|
),
|
||||||
|
"webhooks": ScheduledFunction(
|
||||||
|
scheduler, post_webhooks, Cron(hours=00, minutes=00), "webhooks"
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
scheduler.start()
|
10
mealie/services/scheduler/scheduler_utils.py
Normal file
10
mealie/services/scheduler/scheduler_utils.py
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
import collections
|
||||||
|
|
||||||
|
Cron = collections.namedtuple("Cron", "hours minutes")
|
||||||
|
|
||||||
|
|
||||||
|
def cron_parser(time_str: str) -> Cron:
|
||||||
|
time = time_str.split(":")
|
||||||
|
cron = Cron(hours=int(time[0]), minutes=int(time[1]))
|
||||||
|
|
||||||
|
return cron
|
|
@ -1,73 +0,0 @@
|
||||||
import collections
|
|
||||||
import json
|
|
||||||
|
|
||||||
import requests
|
|
||||||
from apscheduler.schedulers.background import BackgroundScheduler
|
|
||||||
from db.db_setup import create_session
|
|
||||||
from utils.logger import logger
|
|
||||||
|
|
||||||
from services.backups.exports import auto_backup_job
|
|
||||||
from services.meal_services import MealPlan
|
|
||||||
from services.recipe_services import Recipe
|
|
||||||
from services.settings_services import SiteSettings
|
|
||||||
|
|
||||||
Cron = collections.namedtuple("Cron", "hours minutes")
|
|
||||||
|
|
||||||
|
|
||||||
def cron_parser(time_str: str) -> Cron:
|
|
||||||
time = time_str.split(":")
|
|
||||||
cron = Cron(hours=int(time[0]), minutes=int(time[1]))
|
|
||||||
|
|
||||||
return cron
|
|
||||||
|
|
||||||
|
|
||||||
def post_webhooks():
|
|
||||||
all_settings = SiteSettings.get_site_settings()
|
|
||||||
|
|
||||||
if all_settings.webhooks.enabled:
|
|
||||||
todays_meal = Recipe.get_by_slug(MealPlan.today()).dict()
|
|
||||||
urls = all_settings.webhooks.webhookURLs
|
|
||||||
|
|
||||||
for url in urls:
|
|
||||||
requests.post(url, json.dumps(todays_meal, default=str))
|
|
||||||
|
|
||||||
|
|
||||||
class Scheduler:
|
|
||||||
def startup_scheduler(self):
|
|
||||||
self.scheduler = BackgroundScheduler()
|
|
||||||
logger.info("----INIT SCHEDULE OBJECT-----")
|
|
||||||
self.scheduler.start()
|
|
||||||
|
|
||||||
self.scheduler.add_job(
|
|
||||||
auto_backup_job, trigger="cron", hour="3", max_instances=1
|
|
||||||
)
|
|
||||||
settings = SiteSettings.get_site_settings(create_session())
|
|
||||||
time = cron_parser(settings.webhooks.webhookTime)
|
|
||||||
|
|
||||||
self.webhook = self.scheduler.add_job(
|
|
||||||
post_webhooks,
|
|
||||||
trigger="cron",
|
|
||||||
name="webhooks",
|
|
||||||
hour=time.hours,
|
|
||||||
minute=time.minutes,
|
|
||||||
max_instances=1,
|
|
||||||
)
|
|
||||||
|
|
||||||
logger.info(self.scheduler.print_jobs())
|
|
||||||
|
|
||||||
def reschedule_webhooks(self):
|
|
||||||
"""
|
|
||||||
Reads the site settings database entry to reschedule the webhooks task
|
|
||||||
Called after each post to the webhooks endpoint.
|
|
||||||
"""
|
|
||||||
settings = SiteSettings.get_site_settings()
|
|
||||||
time = cron_parser(settings.webhooks.webhookTime)
|
|
||||||
|
|
||||||
self.scheduler.reschedule_job(
|
|
||||||
self.webhook.id,
|
|
||||||
trigger="cron",
|
|
||||||
hour=time.hours,
|
|
||||||
minute=time.minutes,
|
|
||||||
)
|
|
||||||
|
|
||||||
logger.info(self.scheduler.print_jobs())
|
|
|
@ -1,7 +1,7 @@
|
||||||
from typing import List, Optional
|
from typing import List, Optional
|
||||||
|
|
||||||
from db.database import db
|
from db.database import db
|
||||||
from db.db_setup import create_session, generate_session, sql_exists
|
from db.db_setup import create_session, sql_exists
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
from sqlalchemy.orm.session import Session
|
from sqlalchemy.orm.session import Session
|
||||||
from utils.logger import logger
|
from utils.logger import logger
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
from services.scheduler_services import Scheduler
|
|
||||||
|
|
||||||
|
|
||||||
def start_scheduler():
|
|
||||||
global scheduler
|
|
||||||
scheduler = Scheduler()
|
|
||||||
scheduler.startup_scheduler()
|
|
||||||
return scheduler
|
|
||||||
|
|
||||||
|
|
||||||
scheduler = start_scheduler
|
|
21
mealie/utils/post_webhooks.py
Normal file
21
mealie/utils/post_webhooks.py
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
import json
|
||||||
|
|
||||||
|
import requests
|
||||||
|
from db.db_setup import create_session
|
||||||
|
from services.meal_services import MealPlan
|
||||||
|
from services.recipe_services import Recipe
|
||||||
|
from services.settings_services import SiteSettings
|
||||||
|
|
||||||
|
|
||||||
|
def post_webhooks():
|
||||||
|
session = create_session()
|
||||||
|
all_settings = SiteSettings.get_site_settings(session)
|
||||||
|
|
||||||
|
if all_settings.webhooks.enabled:
|
||||||
|
todays_meal = Recipe.get_by_slug(MealPlan.today()).dict()
|
||||||
|
urls = all_settings.webhooks.webhookURLs
|
||||||
|
|
||||||
|
for url in urls:
|
||||||
|
requests.post(url, json.dumps(todays_meal, default=str))
|
||||||
|
|
||||||
|
session.close()
|
Loading…
Add table
Add a link
Reference in a new issue