jasquat 18600189c8 Feature/background proc with celery (#788)
* WIP: some initial test code to test out celery w/ burnettk

* some cleanup for celery and added base model to put tasks waiting on timers

* removed dup bpmn file

* some more cleanup and added strategy to queue instructions

* some minor code changes w/ burnettk

* remove the unused next_task key from api calls since nobody uses it w/ burnettk essweine

* added migration for future tasks and added test to make sure we are inserting into it w/ burnettk essweine

* ensure future task run at time can be updated w/ burnettk

* added table to queue instructions for end user in w/ burnettk

* added test to ensure we are storing instructions for end users w/ burnettk

* added progress page to display new instructions to user

* ignore dup instructions on db insert w/ burnettk

* some more updates for celery w/ burnettk

* some pyl and test fixes w/ burnettk

* fixed tests w/ burnettk

* WIP: added in page to show instructions on pi show page w/ burnettk

* pi show page is fully using not interstitial now w/ burnettk

* fixed broken test w/ burnettk

* moved background processing items to own module w/ burnettk

* fixed apscheduler start script

* updated celery task queue to handle future tasks and upgraded black and set its line-length to match ruff w/ burnettk

* added support to run future tasks using countdown w/ burnettk

* build image for celery branch w/ burnettk

* poet does not exist in the image w/ burnettk

* start blocking scheduler should always start the scheduler w/ burnettk

* add init and stuff for this branch

* make this work not just on my mac

* send other args to only

* added running status for process instance and use that on fe to go to show page and added additional identifier to locking system to isolate celery workers better w/ burnettk

* fixed typing error that typeguard found, not sure why mypy did not w/ burnettk

* do not check for no instructions on interstitial page for cypress tests on frontend w/ burnettk

* do not queue process instances twice w/ burnettk

* removed bad file w/ burnettk

* queue tasks using strings to avoid circular imports when attmepting to queue w/ burnettk

* only queue imminent new timer events and mock celery

* some keyboard shortcut support on frontend and added ability to force run a process instance over the api w/ burnettk

* some styles added for the shortcut menu w/ burnettk

* pyl w/ burnettk

* fixed test w/ burnettk

* removed temporary celery script and added support for celery worker in run server locally w/ burnettk

* cleaned up migrations w/ burnettk

* created new migration to clean up old migrations

---------

Co-authored-by: jasquat <jasquat@users.noreply.github.com>
Co-authored-by: burnettk <burnettk@users.noreply.github.com>
2023-12-05 11:41:59 -05:00

84 lines
2.9 KiB
Python

import time
from flask import current_app
from spiffworkflow_backend import create_app
from spiffworkflow_backend.data_migrations.version_1_3 import VersionOneThree
from spiffworkflow_backend.data_migrations.version_2 import Version2
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.process_instance import ProcessInstanceModel
from sqlalchemy import update
# simple decorator to time the func
# https://stackoverflow.com/a/11151365/6090676, thank you
def benchmark_log_func(func):
"""
decorator to calculate the total time of a func
"""
def st_func(*args, **kwargs):
t1 = time.time()
r = func(*args, **kwargs)
t2 = time.time()
# __qualname__, i know you use it every day. but if not, it's the function name prefixed with any qualifying class names
current_app.logger.debug(f"Function={func.__qualname__}, Time={t2 - t1}")
return r
return st_func
@benchmark_log_func
def put_serializer_version_onto_numeric_track() -> None:
old_busted_serializer_version = "1.0-spiffworkflow-backend"
update_query = (
update(ProcessInstanceModel)
.where(ProcessInstanceModel.spiff_serializer_version == old_busted_serializer_version)
.values(spiff_serializer_version="1")
)
db.session.execute(update_query)
db.session.commit()
def all_potentially_relevant_process_instances() -> list[ProcessInstanceModel]:
return ProcessInstanceModel.query.filter(
ProcessInstanceModel.spiff_serializer_version < Version2.version(),
ProcessInstanceModel.status.in_(ProcessInstanceModel.non_terminal_statuses()),
).all()
@benchmark_log_func
def run_version_1() -> None:
VersionOneThree().run() # make this a class method
@benchmark_log_func
def run_version_2(process_instances: list[ProcessInstanceModel]) -> None:
Version2.run(process_instances)
def main() -> None:
start_time = time.time()
app = create_app()
end_time = time.time()
with app.app_context():
current_app.logger.debug(f"data_migrations/run_all::create_app took {end_time - start_time} seconds")
start_time = time.time()
put_serializer_version_onto_numeric_track()
process_instances = all_potentially_relevant_process_instances()
potentially_relevant_instance_count = len(process_instances)
current_app.logger.debug(f"Found potentially relevant process_instances: {potentially_relevant_instance_count}")
if potentially_relevant_instance_count > 0:
run_version_1()
# this will run while using the new per instance on demand data migration framework
# run_version_2(process_instances)
end_time = time.time()
current_app.logger.debug(
f"done running data migrations in ./bin/data_migrations/run_all.py. took {end_time - start_time} seconds"
)
if __name__ == "__main__":
main()