From 576bf6bb89216efa3fe517587b60ea8b6e3d4b2e Mon Sep 17 00:00:00 2001 From: Ben Rog-Wilhelm Date: Sat, 22 Apr 2023 04:34:40 -0500 Subject: [PATCH] Add a `cron_setup` task to initialize code-defined cron tasks. --- bootstrap/init.sh | 1 + files/classes/cron/tasks.py | 5 +- files/cli.py | 1 + files/commands/cron_setup.py | 52 +++++++++++++++++++ ...2_07_57_45_0cd3a7ebef3f_add_cron_labels.py | 30 +++++++++++ 5 files changed, 88 insertions(+), 1 deletion(-) mode change 100644 => 100755 bootstrap/init.sh create mode 100644 files/commands/cron_setup.py create mode 100644 migrations/versions/2023_04_22_07_57_45_0cd3a7ebef3f_add_cron_labels.py diff --git a/bootstrap/init.sh b/bootstrap/init.sh old mode 100644 new mode 100755 index 054238a19..6948b22d7 --- a/bootstrap/init.sh +++ b/bootstrap/init.sh @@ -2,5 +2,6 @@ set -euxo pipefail python3 -m flask db upgrade # this does not actually return error codes properly! +python3 -m flask cron_setup /usr/local/bin/supervisord -c /etc/supervisord.conf diff --git a/files/classes/cron/tasks.py b/files/classes/cron/tasks.py index 78ce9eb27..52a45bb6f 100644 --- a/files/classes/cron/tasks.py +++ b/files/classes/cron/tasks.py @@ -13,7 +13,7 @@ import redis from sqlalchemy.orm import relationship, Session from sqlalchemy.schema import Column, ForeignKey from sqlalchemy.sql.sqltypes import (Boolean, DateTime, Integer, SmallInteger, - Text, Time) + Text, Time, String) from files.classes.base import CreatedBase from files.helpers.time import format_age, format_datetime @@ -247,6 +247,9 @@ class RepeatableTask(CreatedBase): frequency_day = Column(SmallInteger, nullable=False) time_of_day_utc = Column(Time, nullable=False) + # used for the cron hardcoding system + label = Column(String, nullable=True, unique=True) + runs = relationship("RepeatableTaskRun", back_populates="task") @property diff --git a/files/cli.py b/files/cli.py index 6f655923b..b702bc31b 100644 --- a/files/cli.py +++ b/files/cli.py @@ -4,6 +4,7 @@ from flask_sqlalchemy import SQLAlchemy from files.__main__ import app from files.commands.cron import cron_app_worker from files.commands.seed_db import seed_db +from files.commands.cron_setup import cron_setup import files.classes db = SQLAlchemy(app) diff --git a/files/commands/cron_setup.py b/files/commands/cron_setup.py new file mode 100644 index 000000000..d7bad3672 --- /dev/null +++ b/files/commands/cron_setup.py @@ -0,0 +1,52 @@ + +from typing import Optional +import datetime + +import sqlalchemy +from sqlalchemy.orm import Session + +from files.__main__ import app, db_session +from files.classes.cron.pycallable import PythonCodeTask +from files.classes.cron.tasks import DayOfWeek +from files.helpers.config.const import AUTOJANNY_ID + + +@app.cli.command('cron_setup') +def cron_setup(): + db: Session = db_session() + + tasklist = db.query(PythonCodeTask) + + # I guess in theory we should load this from a file or something, but, ehhhh + hardcoded_cron_jobs = { + #'testjob': { + #'frequency_day': DayOfWeek.ALL, + #'time_of_day_utc': datetime.time(0, 0), + #'import_path': 'files.commands.debug_printout', + #'callable': 'printstuff', + #}, + } + + print(f"{tasklist.count()} tasks") + for task in tasklist: + if task.label and task.label in hardcoded_cron_jobs: + print(f"Cron: Updating {task.label}") + ref = hardcoded_cron_jobs[task.label] + task.frequency_day = ref["frequency_day"] + task.time_of_day_utc = ref["time_of_day_utc"] + task.import_path = ref["import_path"] + task.callable = ref["callable"] + del hardcoded_cron_jobs[task.label] + + for label, ref in hardcoded_cron_jobs.items(): + print(f"Cron: Creating {label}") + task = PythonCodeTask() + task.label = label + task.author_id = AUTOJANNY_ID + task.frequency_day = ref["frequency_day"] + task.time_of_day_utc = ref["time_of_day_utc"] + task.import_path = ref["import_path"] + task.callable = ref["callable"] + db.add(task) + + db.commit() diff --git a/migrations/versions/2023_04_22_07_57_45_0cd3a7ebef3f_add_cron_labels.py b/migrations/versions/2023_04_22_07_57_45_0cd3a7ebef3f_add_cron_labels.py new file mode 100644 index 000000000..5ce1ea2a5 --- /dev/null +++ b/migrations/versions/2023_04_22_07_57_45_0cd3a7ebef3f_add_cron_labels.py @@ -0,0 +1,30 @@ +"""add cron labels + +Revision ID: 0cd3a7ebef3f +Revises: 6b6c1b21a487 +Create Date: 2023-04-22 07:57:45.164146+00:00 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = '0cd3a7ebef3f' +down_revision = '6b6c1b21a487' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.add_column('tasks_repeatable', sa.Column('label', sa.String(), nullable=True)) + op.create_unique_constraint(None, 'tasks_repeatable', ['label']) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_constraint(None, 'tasks_repeatable', type_='unique') + op.drop_column('tasks_repeatable', 'label') + # ### end Alembic commands ###