From 2f4905195f00d6f878b1046396f023bf1ae624d0 Mon Sep 17 00:00:00 2001 From: Florian Reisinger Date: Fri, 30 Aug 2024 16:13:28 +1000 Subject: [PATCH] Extend API capabilities - Add ongoing endpoint to allow listing of non-terminal workflow runs - Update mock data to include non-terminal workflow run states --- .../commands/generate_mock_workflow_run.py | 33 +++++++++---------- .../workflow_manager/viewsets/workflow_run.py | 25 ++++++++++++++ 2 files changed, 41 insertions(+), 17 deletions(-) diff --git a/lib/workload/stateless/stacks/workflow-manager/workflow_manager/management/commands/generate_mock_workflow_run.py b/lib/workload/stateless/stacks/workflow-manager/workflow_manager/management/commands/generate_mock_workflow_run.py index d0e995a1a..1b1a4c21b 100644 --- a/lib/workload/stateless/stacks/workflow-manager/workflow_manager/management/commands/generate_mock_workflow_run.py +++ b/lib/workload/stateless/stacks/workflow-manager/workflow_manager/management/commands/generate_mock_workflow_run.py @@ -1,11 +1,8 @@ from django.core.management import BaseCommand -from django.db.models import QuerySet from django.utils.timezone import make_aware -import json -from datetime import datetime -from libumccr import libjson -from workflow_manager.models import Workflow, WorkflowRun, LibraryAssociation, State +from datetime import datetime, timedelta +from workflow_manager.models import Workflow, WorkflowRun, LibraryAssociation from workflow_manager.tests.factories import WorkflowRunFactory, WorkflowFactory, PayloadFactory, LibraryFactory, \ StateFactory @@ -17,6 +14,7 @@ STATUS_END = "SUCCEEDED" STATUS_FAIL = "FAILED" + # https://docs.djangoproject.com/en/5.0/howto/custom-management-commands/ class Command(BaseCommand): help = """ @@ -60,8 +58,9 @@ def create_primary(generic_payload, libraries): portal_run_id="1234", workflow=wf ) - for state in [STATUS_DRAFT, STATUS_START, STATUS_RUNNING, STATUS_FAIL]: - StateFactory(workflow_run=wfr_1, status=state, payload=generic_payload) + + for i, state in enumerate([STATUS_DRAFT, STATUS_START, STATUS_RUNNING, STATUS_FAIL]): + StateFactory(workflow_run=wfr_1, status=state, payload=generic_payload, timestamp=make_aware(datetime.now() + timedelta(hours=i))) for i in [0, 1, 2, 3]: LibraryAssociation.objects.create( workflow_run=wfr_1, @@ -76,8 +75,8 @@ def create_primary(generic_payload, libraries): portal_run_id="1235", workflow=wf ) - for state in [STATUS_DRAFT, STATUS_START, STATUS_RUNNING, STATUS_END]: - StateFactory(workflow_run=wfr_2, status=state, payload=generic_payload) + for i, state in enumerate([STATUS_DRAFT, STATUS_START, STATUS_RUNNING, STATUS_END]): + StateFactory(workflow_run=wfr_2, status=state, payload=generic_payload, timestamp=make_aware(datetime.now() + timedelta(hours=i))) for i in [0, 1, 2, 3]: LibraryAssociation.objects.create( workflow_run=wfr_2, @@ -103,8 +102,8 @@ def create_secondary(generic_payload, libraries): portal_run_id="2345", workflow=wf_qc ) - for state in [STATUS_DRAFT, STATUS_START, STATUS_RUNNING, STATUS_END]: - StateFactory(workflow_run=wfr_qc_1, status=state, payload=generic_payload) + for i, state in enumerate([STATUS_DRAFT, STATUS_START, STATUS_RUNNING, STATUS_END]): + StateFactory(workflow_run=wfr_qc_1, status=state, payload=generic_payload, timestamp=make_aware(datetime.now() + timedelta(hours=i))) LibraryAssociation.objects.create( workflow_run=wfr_qc_1, library=libraries[0], @@ -118,8 +117,8 @@ def create_secondary(generic_payload, libraries): portal_run_id="2346", workflow=wf_qc ) - for state in [STATUS_DRAFT, STATUS_START, STATUS_RUNNING, STATUS_END]: - StateFactory(workflow_run=wfr_qc_2, status=state, payload=generic_payload) + for i, state in enumerate([STATUS_DRAFT, STATUS_START, STATUS_RUNNING, STATUS_END]): + StateFactory(workflow_run=wfr_qc_2, status=state, payload=generic_payload, timestamp=make_aware(datetime.now() + timedelta(hours=i))) LibraryAssociation.objects.create( workflow_run=wfr_qc_2, library=libraries[1], @@ -134,8 +133,8 @@ def create_secondary(generic_payload, libraries): portal_run_id="3456", workflow=wf_align ) - for state in [STATUS_DRAFT, STATUS_START, STATUS_RUNNING, STATUS_END]: - StateFactory(workflow_run=wfr_a, status=state, payload=generic_payload) + for i, state in enumerate([STATUS_DRAFT, STATUS_START]): + StateFactory(workflow_run=wfr_a, status=state, payload=generic_payload, timestamp=make_aware(datetime.now() + timedelta(hours=i))) for i in [0, 1]: LibraryAssociation.objects.create( workflow_run=wfr_a, @@ -151,8 +150,8 @@ def create_secondary(generic_payload, libraries): portal_run_id="4567", workflow=wf_vc ) - for state in [STATUS_DRAFT, STATUS_START, STATUS_RUNNING, STATUS_END]: - StateFactory(workflow_run=wfr_vc, status=state, payload=generic_payload) + for i, state in enumerate([STATUS_DRAFT, STATUS_START, STATUS_RUNNING]): + StateFactory(workflow_run=wfr_vc, status=state, payload=generic_payload, timestamp=make_aware(datetime.now() + timedelta(hours=i))) for i in [0, 1]: LibraryAssociation.objects.create( workflow_run=wfr_vc, diff --git a/lib/workload/stateless/stacks/workflow-manager/workflow_manager/viewsets/workflow_run.py b/lib/workload/stateless/stacks/workflow-manager/workflow_manager/viewsets/workflow_run.py index 842abc907..8a3b1d1d4 100644 --- a/lib/workload/stateless/stacks/workflow-manager/workflow_manager/viewsets/workflow_run.py +++ b/lib/workload/stateless/stacks/workflow-manager/workflow_manager/viewsets/workflow_run.py @@ -1,4 +1,6 @@ +from django.db.models import Q from rest_framework import filters +from rest_framework.decorators import action from rest_framework.viewsets import ReadOnlyModelViewSet from workflow_manager.models.workflow_run import WorkflowRun @@ -16,3 +18,26 @@ class WorkflowRunViewSet(ReadOnlyModelViewSet): def get_queryset(self): return WorkflowRun.objects.get_by_keyword(**self.request.query_params) + + @action(detail=False, methods=['GET']) + def ongoing(self, request): + # Get all books marked as favorite + print(request) + print(self.request.query_params) + ordering = self.request.query_params.get('ordering', '-id') + + if "status" in self.request.query_params.keys(): + print("found status!") + status = self.request.query_params.get('status') + result_set = WorkflowRun.objects.get_by_keyword(state__status=status).order_by(ordering) + else: + result_set = WorkflowRun.objects.get_by_keyword(**self.request.query_params).order_by(ordering) + + result_set = result_set.filter( + ~Q(state__status="FAILED") & + ~Q(state__status="ABORTED") & + ~Q(state__status="SUCCEEDED") + ) + pagw_qs = self.paginate_queryset(result_set) + serializer = self.get_serializer(pagw_qs, many=True) + return self.get_paginated_response(serializer.data)