mirror of
https://github.com/sartography/spiffworkflow-backend.git
synced 2025-02-24 13:28:31 +00:00
Merge pull request #95 from sartography/feature/background-process-waiting-tasks
Feature/background process waiting tasks
This commit is contained in:
commit
adbc521cf0
@ -29,10 +29,10 @@ if [[ "${1:-}" == "clean" ]]; then
|
|||||||
if [[ "${SPIFF_DATABASE_TYPE:-}" == "postgres" ]]; then
|
if [[ "${SPIFF_DATABASE_TYPE:-}" == "postgres" ]]; then
|
||||||
if ! docker exec -it postgres-spiff psql -U spiffworkflow_backend spiffworkflow_backend_testing -c "select 1"; then
|
if ! docker exec -it postgres-spiff psql -U spiffworkflow_backend spiffworkflow_backend_testing -c "select 1"; then
|
||||||
docker run --name postgres-spiff -p 5432:5432 -e POSTGRES_PASSWORD=spiffworkflow_backend -e POSTGRES_USER=spiffworkflow_backend -e POSTGRES_DB=spiffworkflow_backend_testing -d postgres
|
docker run --name postgres-spiff -p 5432:5432 -e POSTGRES_PASSWORD=spiffworkflow_backend -e POSTGRES_USER=spiffworkflow_backend -e POSTGRES_DB=spiffworkflow_backend_testing -d postgres
|
||||||
|
|
||||||
sleep 4 # classy
|
sleep 4 # classy
|
||||||
|
fi
|
||||||
# create other db
|
if ! docker exec -it postgres-spiff psql -U spiffworkflow_backend spiffworkflow_backend_development -c "select 1"; then
|
||||||
|
# create other db. spiffworkflow_backend_testing came with the docker run.
|
||||||
docker exec -it postgres-spiff psql -U spiffworkflow_backend spiffworkflow_backend_testing -c "create database spiffworkflow_backend_development;"
|
docker exec -it postgres-spiff psql -U spiffworkflow_backend spiffworkflow_backend_testing -c "create database spiffworkflow_backend_development;"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
@ -17,7 +17,9 @@ from spiffworkflow_backend.config import setup_config
|
|||||||
from spiffworkflow_backend.routes.admin_blueprint.admin_blueprint import admin_blueprint
|
from spiffworkflow_backend.routes.admin_blueprint.admin_blueprint import admin_blueprint
|
||||||
from spiffworkflow_backend.routes.process_api_blueprint import process_api_blueprint
|
from spiffworkflow_backend.routes.process_api_blueprint import process_api_blueprint
|
||||||
from spiffworkflow_backend.routes.user_blueprint import user_blueprint
|
from spiffworkflow_backend.routes.user_blueprint import user_blueprint
|
||||||
from spiffworkflow_backend.services.message_service import MessageServiceWithAppContext
|
from spiffworkflow_backend.services.background_processing_service import (
|
||||||
|
BackgroundProcessingService,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class MyJSONEncoder(flask.json.JSONEncoder):
|
class MyJSONEncoder(flask.json.JSONEncoder):
|
||||||
@ -34,10 +36,15 @@ def start_scheduler(app: flask.app.Flask) -> None:
|
|||||||
"""Start_scheduler."""
|
"""Start_scheduler."""
|
||||||
scheduler = BackgroundScheduler()
|
scheduler = BackgroundScheduler()
|
||||||
scheduler.add_job(
|
scheduler.add_job(
|
||||||
MessageServiceWithAppContext(app).process_message_instances_with_app_context,
|
BackgroundProcessingService(app).process_message_instances_with_app_context,
|
||||||
"interval",
|
"interval",
|
||||||
seconds=10,
|
seconds=10,
|
||||||
)
|
)
|
||||||
|
scheduler.add_job(
|
||||||
|
BackgroundProcessingService(app).run,
|
||||||
|
"interval",
|
||||||
|
seconds=30,
|
||||||
|
)
|
||||||
scheduler.start()
|
scheduler.start()
|
||||||
|
|
||||||
|
|
||||||
|
@ -79,6 +79,7 @@ class ProcessInstanceStatus(SpiffEnum):
|
|||||||
faulted = "faulted"
|
faulted = "faulted"
|
||||||
suspended = "suspended"
|
suspended = "suspended"
|
||||||
terminated = "terminated"
|
terminated = "terminated"
|
||||||
|
erroring = "erroring"
|
||||||
|
|
||||||
|
|
||||||
class ProcessInstanceModel(SpiffworkflowBaseDBModel):
|
class ProcessInstanceModel(SpiffworkflowBaseDBModel):
|
||||||
|
@ -0,0 +1,25 @@
|
|||||||
|
"""Background_processing_service."""
|
||||||
|
import flask
|
||||||
|
|
||||||
|
from spiffworkflow_backend.services.message_service import MessageService
|
||||||
|
from spiffworkflow_backend.services.process_instance_service import (
|
||||||
|
ProcessInstanceService,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class BackgroundProcessingService:
|
||||||
|
"""Used to facilitate doing work outside of an HTTP request/response."""
|
||||||
|
|
||||||
|
def __init__(self, app: flask.app.Flask):
|
||||||
|
"""__init__."""
|
||||||
|
self.app = app
|
||||||
|
|
||||||
|
def run(self) -> None:
|
||||||
|
"""Since this runs in a scheduler, we need to specify the app context as well."""
|
||||||
|
with self.app.app_context():
|
||||||
|
ProcessInstanceService.do_waiting()
|
||||||
|
|
||||||
|
def process_message_instances_with_app_context(self) -> None:
|
||||||
|
"""Since this runs in a scheduler, we need to specify the app context as well."""
|
||||||
|
with self.app.app_context():
|
||||||
|
MessageService.process_message_instances()
|
@ -2,7 +2,6 @@
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
import flask
|
|
||||||
from flask_bpmn.models.db import db
|
from flask_bpmn.models.db import db
|
||||||
from sqlalchemy import and_
|
from sqlalchemy import and_
|
||||||
from sqlalchemy import or_
|
from sqlalchemy import or_
|
||||||
@ -26,23 +25,6 @@ from spiffworkflow_backend.services.process_instance_service import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class MessageServiceWithAppContext:
|
|
||||||
"""Wrapper for Message Service.
|
|
||||||
|
|
||||||
This wrappers is to facilitate running the MessageService from the scheduler
|
|
||||||
since we need to specify the app context then.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, app: flask.app.Flask):
|
|
||||||
"""__init__."""
|
|
||||||
self.app = app
|
|
||||||
|
|
||||||
def process_message_instances_with_app_context(self) -> None:
|
|
||||||
"""Since this runs in a scheduler, we need to specify the app context as well."""
|
|
||||||
with self.app.app_context():
|
|
||||||
MessageService.process_message_instances()
|
|
||||||
|
|
||||||
|
|
||||||
class MessageServiceError(Exception):
|
class MessageServiceError(Exception):
|
||||||
"""MessageServiceError."""
|
"""MessageServiceError."""
|
||||||
|
|
||||||
|
@ -58,6 +58,30 @@ class ProcessInstanceService:
|
|||||||
db.session.commit()
|
db.session.commit()
|
||||||
return process_instance_model
|
return process_instance_model
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def do_waiting() -> None:
|
||||||
|
"""Do_waiting."""
|
||||||
|
records = (
|
||||||
|
db.session.query(ProcessInstanceModel)
|
||||||
|
.filter(ProcessInstanceModel.status == ProcessInstanceStatus.waiting.value)
|
||||||
|
.all()
|
||||||
|
)
|
||||||
|
for process_instance in records:
|
||||||
|
try:
|
||||||
|
current_app.logger.info(
|
||||||
|
f"Processing process_instance {process_instance.id}"
|
||||||
|
)
|
||||||
|
processor = ProcessInstanceProcessor(process_instance)
|
||||||
|
processor.do_engine_steps(save=True)
|
||||||
|
except Exception:
|
||||||
|
db.session.rollback() # in case the above left the database with a bad transaction
|
||||||
|
process_instance.status = ProcessInstanceStatus.erroring.value
|
||||||
|
db.session.add(process_instance)
|
||||||
|
db.session.commit()
|
||||||
|
error_message = f"Error running waiting task for process_instance {process_instance.id}"
|
||||||
|
"({process_instance.process_model_identifier}). {str(e)}"
|
||||||
|
current_app.logger.error(error_message)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def processor_to_process_instance_api(
|
def processor_to_process_instance_api(
|
||||||
processor: ProcessInstanceProcessor, next_task: None = None
|
processor: ProcessInstanceProcessor, next_task: None = None
|
||||||
|
@ -188,8 +188,10 @@ class TestMessageService(BaseTest):
|
|||||||
process_instance_result = ProcessInstanceModel.query.all()
|
process_instance_result = ProcessInstanceModel.query.all()
|
||||||
|
|
||||||
assert len(process_instance_result) == 3
|
assert len(process_instance_result) == 3
|
||||||
process_instance_receiver_one = process_instance_result[1]
|
process_instance_receiver_one = ProcessInstanceModel.query.filter_by(process_model_identifier='message_receiver_one').first()
|
||||||
process_instance_receiver_two = process_instance_result[2]
|
assert process_instance_receiver_one is not None
|
||||||
|
process_instance_receiver_two = ProcessInstanceModel.query.filter_by(process_model_identifier='message_receiver_two').first()
|
||||||
|
assert process_instance_receiver_two is not None
|
||||||
|
|
||||||
# just make sure it's a different process instance
|
# just make sure it's a different process instance
|
||||||
assert (
|
assert (
|
||||||
|
Loading…
x
Reference in New Issue
Block a user