diff --git a/docs/docs/overrides/api.html b/docs/docs/overrides/api.html index ea25a4ac3f5a..2f8571381f78 100644 --- a/docs/docs/overrides/api.html +++ b/docs/docs/overrides/api.html @@ -14,7 +14,7 @@
diff --git a/frontend/layouts/admin.vue b/frontend/layouts/admin.vue index c6222faa40bd..7db321ab929f 100644 --- a/frontend/layouts/admin.vue +++ b/frontend/layouts/admin.vue @@ -85,12 +85,6 @@ export default defineComponent({ title: i18n.tc("sidebar.maintenance"), restricted: true, }, - { - icon: $globals.icons.check, - to: "/admin/background-tasks", - title: i18n.tc("sidebar.background-tasks"), - restricted: true, - }, { icon: $globals.icons.slotMachine, to: "/admin/parser", diff --git a/frontend/lib/api/admin/admin-tasks.ts b/frontend/lib/api/admin/admin-tasks.ts deleted file mode 100644 index af4635cc341c..000000000000 --- a/frontend/lib/api/admin/admin-tasks.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { BaseAPI } from "../base/base-clients"; -import { ServerTask } from "~/lib/api/types/server"; -import { PaginationData } from "~/lib/api/types/non-generated"; - -const prefix = "/api"; - -const routes = { - base: `${prefix}/admin/server-tasks`, -}; - -export class AdminTaskAPI extends BaseAPI { - async testTask() { - return await this.requests.post(`${routes.base}`, {}); - } - - async getAll() { - return await this.requests.get>(routes.base); - } -} diff --git a/frontend/lib/api/client-admin.ts b/frontend/lib/api/client-admin.ts index c4bc2a148dc9..a0bbca8f80fe 100644 --- a/frontend/lib/api/client-admin.ts +++ b/frontend/lib/api/client-admin.ts @@ -1,5 +1,4 @@ import { AdminAboutAPI } from "./admin/admin-about"; -import { AdminTaskAPI } from "./admin/admin-tasks"; import { AdminUsersApi } from "./admin/admin-users"; import { AdminGroupsApi } from "./admin/admin-groups"; import { AdminBackupsApi } from "./admin/admin-backups"; @@ -9,7 +8,6 @@ import { ApiRequestInstance } from "~/lib/api/types/non-generated"; export class AdminAPI { public about: AdminAboutAPI; - public serverTasks: AdminTaskAPI; public users: AdminUsersApi; public groups: AdminGroupsApi; public backups: AdminBackupsApi; @@ -18,7 +16,6 @@ export class AdminAPI { constructor(requests: ApiRequestInstance) { this.about = new AdminAboutAPI(requests); - this.serverTasks = new AdminTaskAPI(requests); this.users = new AdminUsersApi(requests); this.groups = new AdminGroupsApi(requests); this.backups = new AdminBackupsApi(requests); diff --git a/frontend/lib/api/client-user.ts b/frontend/lib/api/client-user.ts index cc40f42f35c8..2678b13f6c69 100644 --- a/frontend/lib/api/client-user.ts +++ b/frontend/lib/api/client-user.ts @@ -15,7 +15,6 @@ import { RegisterAPI } from "./user/user-registration"; import { MealPlanAPI } from "./user/group-mealplan"; import { EmailAPI } from "./user/email"; import { BulkActionsAPI } from "./user/recipe-bulk-actions"; -import { GroupServerTaskAPI } from "./user/group-tasks"; import { ToolsApi } from "./user/organizer-tools"; import { GroupMigrationApi } from "./user/group-migrations"; import { GroupReportsApi } from "./user/group-reports"; @@ -46,7 +45,6 @@ export class UserApiClient { public bulk: BulkActionsAPI; public groupMigration: GroupMigrationApi; public groupReports: GroupReportsApi; - public grouperServerTasks: GroupServerTaskAPI; public tools: ToolsApi; public shopping: ShoppingApi; public multiPurposeLabels: MultiPurposeLabelsApi; @@ -72,7 +70,6 @@ export class UserApiClient { this.register = new RegisterAPI(requests); this.mealplans = new MealPlanAPI(requests); this.mealplanRules = new MealPlanRulesApi(requests); - this.grouperServerTasks = new GroupServerTaskAPI(requests); // Group this.groupMigration = new GroupMigrationApi(requests); diff --git a/frontend/lib/api/types/server.ts b/frontend/lib/api/types/server.ts deleted file mode 100644 index 5b994f11c026..000000000000 --- a/frontend/lib/api/types/server.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* tslint:disable */ -/* eslint-disable */ -/** -/* This file was automatically generated from pydantic models by running pydantic2ts. -/* Do not modify it by hand - just update the pydantic models and then re-run the script -*/ - -export type ServerTaskNames = "Background Task" | "Database Backup" | "Bulk Recipe Import"; -export type ServerTaskStatus = "running" | "finished" | "failed"; - -export interface ServerTask { - groupId: string; - name?: ServerTaskNames & string; - createdAt?: string; - status?: ServerTaskStatus & string; - log?: string; - id: number; -} -export interface ServerTaskCreate { - groupId: string; - name?: ServerTaskNames & string; - createdAt?: string; - status?: ServerTaskStatus & string; - log?: string; -} diff --git a/frontend/lib/api/user/group-tasks.ts b/frontend/lib/api/user/group-tasks.ts deleted file mode 100644 index 076af4db0456..000000000000 --- a/frontend/lib/api/user/group-tasks.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { BaseAPI } from "../base/base-clients"; -import { ServerTask } from "~/lib/api/types/server"; -const prefix = "/api"; - -const routes = { - base: `${prefix}/groups/server-tasks`, -}; - -export class GroupServerTaskAPI extends BaseAPI { - async getAll() { - return await this.requests.get(routes.base); - } -} diff --git a/frontend/pages/admin/background-tasks.vue b/frontend/pages/admin/background-tasks.vue deleted file mode 100644 index dba14b2adbae..000000000000 --- a/frontend/pages/admin/background-tasks.vue +++ /dev/null @@ -1,87 +0,0 @@ - - - diff --git a/mealie/db/models/group/group.py b/mealie/db/models/group/group.py index d344ce58b054..b0c74e914a72 100644 --- a/mealie/db/models/group/group.py +++ b/mealie/db/models/group/group.py @@ -15,13 +15,19 @@ from .._model_utils import GUID, auto_init from ..group.invite_tokens import GroupInviteToken from ..group.webhooks import GroupWebhooksModel from ..recipe.category import Category, group_to_categories -from ..server.task import ServerTaskModel from .cookbook import CookBook from .mealplan import GroupMealPlan from .preferences import GroupPreferencesModel if TYPE_CHECKING: - from ..recipe import IngredientFoodModel, IngredientUnitModel, RecipeModel, Tag, Tool + from ..recipe import ( + IngredientFoodModel, + IngredientUnitModel, + RecipeModel, + Tag, + Tool, + ) + from ..server.task import ServerTaskModel from ..users import User from .events import GroupEventNotifierModel from .exports import GroupDataExportsModel @@ -67,7 +73,7 @@ class Group(SqlAlchemyBase, BaseMixins): webhooks: Mapped[list[GroupWebhooksModel]] = orm.relationship(GroupWebhooksModel, **common_args) recipe_actions: Mapped[list["GroupRecipeAction"]] = orm.relationship("GroupRecipeAction", **common_args) cookbooks: Mapped[list[CookBook]] = orm.relationship(CookBook, **common_args) - server_tasks: Mapped[list[ServerTaskModel]] = orm.relationship(ServerTaskModel, **common_args) + server_tasks: Mapped[list["ServerTaskModel"]] = orm.relationship("ServerTaskModel", **common_args) data_exports: Mapped[list["GroupDataExportsModel"]] = orm.relationship("GroupDataExportsModel", **common_args) shopping_lists: Mapped[list["ShoppingList"]] = orm.relationship("ShoppingList", **common_args) group_reports: Mapped[list["ReportModel"]] = orm.relationship("ReportModel", **common_args) diff --git a/mealie/db/models/server/task.py b/mealie/db/models/server/task.py index 420b68978297..b599e1ac3d04 100644 --- a/mealie/db/models/server/task.py +++ b/mealie/db/models/server/task.py @@ -14,6 +14,8 @@ if TYPE_CHECKING: class ServerTaskModel(SqlAlchemyBase, BaseMixins): + # Server Tasks are deprecated, but the table still exists in the database + __tablename__ = "server_tasks" name: Mapped[str] = mapped_column(String, nullable=False) completed_date: Mapped[datetime] = mapped_column(DateTime, nullable=True) diff --git a/mealie/repos/repository_factory.py b/mealie/repos/repository_factory.py index 5116f7ab7b47..f9f3064a1bb4 100644 --- a/mealie/repos/repository_factory.py +++ b/mealie/repos/repository_factory.py @@ -29,7 +29,6 @@ from mealie.db.models.recipe.recipe_timeline import RecipeTimelineEvent from mealie.db.models.recipe.shared import RecipeShareTokenModel from mealie.db.models.recipe.tag import Tag from mealie.db.models.recipe.tool import Tool -from mealie.db.models.server.task import ServerTaskModel from mealie.db.models.users import LongLiveToken, User from mealie.db.models.users.password_reset import PasswordResetModel from mealie.db.models.users.user_to_recipe import UserToRecipe @@ -59,7 +58,6 @@ from mealie.schema.recipe.recipe_ingredient import IngredientFood, IngredientUni from mealie.schema.recipe.recipe_share_token import RecipeShareToken from mealie.schema.recipe.recipe_timeline_events import RecipeTimelineEventOut from mealie.schema.reports.reports import ReportEntryOut, ReportOut -from mealie.schema.server import ServerTask from mealie.schema.user import GroupInDB, LongLiveTokenInDB, PrivateUser from mealie.schema.user.user import UserRatingOut from mealie.schema.user.user_passwords import PrivatePasswordResetToken @@ -162,10 +160,6 @@ class AllRepositories: # ================================================================ # Group - @cached_property - def server_tasks(self) -> RepositoryGeneric[ServerTask, ServerTaskModel]: - return RepositoryGeneric(self.session, PK_ID, ServerTaskModel, ServerTask) - @cached_property def groups(self) -> RepositoryGroup: return RepositoryGroup(self.session, PK_ID, Group, GroupInDB) diff --git a/mealie/routes/admin/__init__.py b/mealie/routes/admin/__init__.py index 81766370cd64..896b057bf479 100644 --- a/mealie/routes/admin/__init__.py +++ b/mealie/routes/admin/__init__.py @@ -8,7 +8,6 @@ from . import ( admin_maintenance, admin_management_groups, admin_management_users, - admin_server_tasks, ) router = AdminAPIRouter(prefix="/admin") @@ -17,7 +16,6 @@ router.include_router(admin_about.router, tags=["Admin: About"]) router.include_router(admin_management_users.router, tags=["Admin: Manage Users"]) router.include_router(admin_management_groups.router, tags=["Admin: Manage Groups"]) router.include_router(admin_email.router, tags=["Admin: Email"]) -router.include_router(admin_server_tasks.router, tags=["Admin: Server Tasks"]) router.include_router(admin_backups.router, tags=["Admin: Backups"]) router.include_router(admin_maintenance.router, tags=["Admin: Maintenance"]) router.include_router(admin_analytics.router, tags=["Admin: Analytics"]) diff --git a/mealie/routes/admin/admin_server_tasks.py b/mealie/routes/admin/admin_server_tasks.py deleted file mode 100644 index a179e9b1e78b..000000000000 --- a/mealie/routes/admin/admin_server_tasks.py +++ /dev/null @@ -1,27 +0,0 @@ -from fastapi import BackgroundTasks, Depends - -from mealie.routes._base import BaseAdminController, controller -from mealie.routes._base.routers import UserAPIRouter -from mealie.schema.response.pagination import PaginationQuery -from mealie.schema.server.tasks import ServerTask, ServerTaskNames, ServerTaskPagination -from mealie.services.server_tasks import BackgroundExecutor, test_executor_func - -router = UserAPIRouter() - - -@controller(router) -class AdminServerTasksController(BaseAdminController): - @router.get("/server-tasks", response_model=ServerTaskPagination) - def get_all(self, q: PaginationQuery = Depends(PaginationQuery)): - response = self.repos.server_tasks.page_all( - pagination=q, - override=ServerTask, - ) - - response.set_pagination_guides(router.url_path_for("get_all"), q.model_dump()) - return response - - @router.post("/server-tasks", response_model=ServerTask, status_code=201) - def create_test_tasks(self, bg_tasks: BackgroundTasks): - bg_executor = BackgroundExecutor(self.group.id, self.repos, bg_tasks) - return bg_executor.dispatch(ServerTaskNames.default, test_executor_func) diff --git a/mealie/schema/server/__init__.py b/mealie/schema/server/__init__.py deleted file mode 100644 index 10f20281b89d..000000000000 --- a/mealie/schema/server/__init__.py +++ /dev/null @@ -1,10 +0,0 @@ -# This file is auto-generated by gen_schema_exports.py -from .tasks import ServerTask, ServerTaskCreate, ServerTaskNames, ServerTaskPagination, ServerTaskStatus - -__all__ = [ - "ServerTask", - "ServerTaskCreate", - "ServerTaskNames", - "ServerTaskPagination", - "ServerTaskStatus", -] diff --git a/mealie/schema/server/tasks.py b/mealie/schema/server/tasks.py deleted file mode 100644 index b467a0655d63..000000000000 --- a/mealie/schema/server/tasks.py +++ /dev/null @@ -1,50 +0,0 @@ -import datetime -import enum -from uuid import UUID - -from pydantic import ConfigDict, Field - -from mealie.schema._mealie import MealieModel -from mealie.schema.response.pagination import PaginationBase - - -class ServerTaskNames(str, enum.Enum): - default = "Background Task" - backup_task = "Database Backup" - bulk_recipe_import = "Bulk Recipe Import" - - -class ServerTaskStatus(str, enum.Enum): - running = "running" - finished = "finished" - failed = "failed" - - -class ServerTaskCreate(MealieModel): - group_id: UUID - name: ServerTaskNames = ServerTaskNames.default - created_at: datetime.datetime = Field(default_factory=datetime.datetime.now) - status: ServerTaskStatus = ServerTaskStatus.running - log: str = "" - - def set_running(self) -> None: - self.status = ServerTaskStatus.running - - def set_finished(self) -> None: - self.status = ServerTaskStatus.finished - - def set_failed(self) -> None: - self.status = ServerTaskStatus.failed - - def append_log(self, message: str) -> None: - # Prefix with Timestamp and append new line and join to log - self.log += f"{datetime.datetime.now()}: {message}\n" - - -class ServerTask(ServerTaskCreate): - id: int - model_config = ConfigDict(from_attributes=True) - - -class ServerTaskPagination(PaginationBase): - items: list[ServerTask] diff --git a/mealie/services/server_tasks/__init__.py b/mealie/services/server_tasks/__init__.py deleted file mode 100644 index 24eb41431ba3..000000000000 --- a/mealie/services/server_tasks/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from .background_executory import * diff --git a/mealie/services/server_tasks/background_executory.py b/mealie/services/server_tasks/background_executory.py deleted file mode 100644 index f6463722e691..000000000000 --- a/mealie/services/server_tasks/background_executory.py +++ /dev/null @@ -1,62 +0,0 @@ -from collections.abc import Callable -from random import getrandbits -from time import sleep -from typing import Any - -from fastapi import BackgroundTasks -from pydantic import UUID4 -from sqlalchemy.orm import Session - -from mealie.repos.all_repositories import get_repositories -from mealie.repos.repository_factory import AllRepositories -from mealie.schema.server.tasks import ServerTask, ServerTaskCreate, ServerTaskNames - - -class BackgroundExecutor: - sleep_time = 60 - - def __init__(self, group_id: UUID4, repos: AllRepositories, bg: BackgroundTasks) -> None: - self.group_id = group_id - self.repos = repos - self.background_tasks = bg - - def dispatch(self, task_name: ServerTaskNames, func: Callable, *args: Any, **kwargs: Any) -> ServerTask: - """The dispatch function is a wrapper around the BackgroundTasks class in Starlett. It directly calls - the add_task function and your task will be run in the background. This function all passes the id required - to check on the server tasks in the database and provide updates. - - Tasks that are dispachd by the Background executor should be designed to accept this key word argument - and update the item in the database accordingly. - """ - - server_task = ServerTaskCreate(group_id=self.group_id, name=task_name) - server_task = self.repos.server_tasks.create(server_task) - - self.background_tasks.add_task(func, *args, **kwargs, task_id=server_task.id, session=self.repos.session) - - return server_task - - -def test_executor_func(task_id: int, session: Session) -> None: - database = get_repositories(session) - task = database.server_tasks.get_one(task_id) - - task.append_log("test task has started") - task.append_log("test task sleeping for 60 seconds") - - sleep(BackgroundExecutor.sleep_time) - - task.append_log("test task has finished sleep") - - # Randomly Decide to set to failed or not - - is_fail = bool(getrandbits(1)) - - if is_fail: - task.append_log("test task has failed") - task.set_failed() - else: - task.append_log("test task has succeeded") - task.set_finished() - - database.server_tasks.update(task.id, task) diff --git a/tests/integration_tests/admin_tests/test_admin_background_tasks.py b/tests/integration_tests/admin_tests/test_admin_background_tasks.py deleted file mode 100644 index 8f21e6ee8454..000000000000 --- a/tests/integration_tests/admin_tests/test_admin_background_tasks.py +++ /dev/null @@ -1,21 +0,0 @@ -from fastapi.testclient import TestClient - -from mealie.services.server_tasks.background_executory import BackgroundExecutor -from tests.utils import api_routes -from tests.utils.fixture_schemas import TestUser - - -def test_admin_server_tasks_test_and_get(api_client: TestClient, admin_user: TestUser): - # Bootstrap Timer - BackgroundExecutor.sleep_time = 1 - - response = api_client.post(api_routes.admin_server_tasks, headers=admin_user.token) - assert response.status_code == 201 - - response = api_client.get(api_routes.admin_server_tasks, headers=admin_user.token) - as_dict = response.json()["items"] - - assert len(as_dict) == 1 - - # Reset Timer - BackgroundExecutor.sleep_time = 60 diff --git a/tests/utils/api_routes/__init__.py b/tests/utils/api_routes/__init__.py index 52184d91fe6f..351331ea0897 100644 --- a/tests/utils/api_routes/__init__.py +++ b/tests/utils/api_routes/__init__.py @@ -33,8 +33,6 @@ admin_maintenance_logs = "/api/admin/maintenance/logs" """`/api/admin/maintenance/logs`""" admin_maintenance_storage = "/api/admin/maintenance/storage" """`/api/admin/maintenance/storage`""" -admin_server_tasks = "/api/admin/server-tasks" -"""`/api/admin/server-tasks`""" admin_users = "/api/admin/users" """`/api/admin/users`""" admin_users_password_reset_token = "/api/admin/users/password-reset-token"