diff --git a/server/api/migrations/0002_alter_galaxyworkflowinvocation_status.py b/server/api/migrations/0002_alter_galaxyworkflowinvocation_status.py new file mode 100644 index 0000000000000000000000000000000000000000..0d9e4d91f016115c406e729b0f1f794802134617 --- /dev/null +++ b/server/api/migrations/0002_alter_galaxyworkflowinvocation_status.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.20 on 2023-07-19 08:34 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='galaxyworkflowinvocation', + name='status', + field=models.CharField(choices=[('scheduled', 'Scheduled'), ('running', 'Running'), ('paused', 'Paused'), ('error', 'Error'), ('done', 'Done')], default='scheduled', max_length=10), + ), + ] diff --git a/server/api/models/galaxy.py b/server/api/models/galaxy.py index 41f9f311f1e4f1b9f84c5c88926f1dd244dd4ae0..99e375f42b438b8d30d4e9115a307c364b5d7fe6 100644 --- a/server/api/models/galaxy.py +++ b/server/api/models/galaxy.py @@ -353,7 +353,8 @@ class GalaxyWorkflow(models.Model): class GalaxyWorkflowInvocation(models.Model): class WorkflowInvocationStatus(models.TextChoices): - RUNNING = ("running", "RUNNING") + SCHEDULED = ("scheduled", "Scheduled") + RUNNING = ("running", "Running") PAUSED = ("paused", "Paused") ERROR = ("error", "Error") DONE = ("done", "Done") @@ -367,7 +368,7 @@ class GalaxyWorkflowInvocation(models.Model): status = models.CharField( max_length=10, choices=WorkflowInvocationStatus.choices, - default=WorkflowInvocationStatus.RUNNING, + default=WorkflowInvocationStatus.SCHEDULED, ) class Meta: @@ -387,8 +388,11 @@ class GalaxyWorkflowInvocation(models.Model): workflow_id=self.galaxy_workflow.get_encoded_id(), history_id=self.galaxy_history.get_encoded_id(), ) + print(invocations) if len(invocations) == 1: return invocations[0]["id"] + elif len(invocations) == 0: + return None else: raise Exception(f"Multiple wf invocations for {self.galaxy_workflow}") @@ -401,19 +405,34 @@ class GalaxyWorkflowInvocation(models.Model): def _get_galaxy_invocation(self): """Get galaxy object using bioblend.""" - return self.galaxy_workflow.galaxy_user.bioblend_gi.workflows.show_invocation( - workflow_id=self.galaxy_workflow.get_encoded_id(), - invocation_id=self.get_encoded_id(), - ) + workflow_invocation_id = self.get_encoded_id() + + if workflow_invocation_id is None: + return None + else: + return ( + self.galaxy_workflow.galaxy_user.bioblend_gi.workflows.show_invocation( + workflow_id=self.galaxy_workflow.get_encoded_id(), + invocation_id=workflow_invocation_id, + ) + ) @property def percentage_done(self) -> float: """Retrieve percentage of jobs done for the invocation.""" if self.status == self.WorkflowInvocationStatus.DONE: return 100.0 - step_jobs_summary = self.galaxy_workflow.galaxy_user.bioblend_gi.invocations.get_invocation_step_jobs_summary( - self.get_encoded_id() - ) + + workflow_invocation_id = self.get_encoded_id() + if workflow_invocation_id: + step_jobs_summary = self.galaxy_workflow.galaxy_user.bioblend_gi.invocations.get_invocation_step_jobs_summary( + workflow_invocation_id + ) + else: + self.status = self.WorkflowInvocationStatus.SCHEDULED + self.save() + return 0 + count_states = defaultdict(int) if len(step_jobs_summary) >= 1: for step in step_jobs_summary: @@ -429,8 +448,13 @@ class GalaxyWorkflowInvocation(models.Model): elif "paused" in count_states.keys(): self.status = self.WorkflowInvocationStatus.PAUSED self.save() + else: + self.status = self.WorkflowInvocationStatus.RUNNING + self.save() return percentage_done * 100 else: + self.status = self.WorkflowInvocationStatus.SCHEDULED + self.save() return 0 def synchronize(self): @@ -442,17 +466,14 @@ class GalaxyWorkflowInvocation(models.Model): }: return - galaxy_invocation = self._get_galaxy_invocation() - self.galaxy_state = galaxy_invocation["state"] - self.save() + if self.galaxy_invocation is not None: + self.galaxy_state = self.galaxy_invocation["state"] + self.save() def get_galaxy_invocation(self): galaxy_user = self.galaxy_workflow.galaxy_user gi = galaxy_user.bioblend_gi - invocation = gi.workflows.show_invocation( - workflow_id=self.galaxy_workflow.get_encoded_id(), - invocation_id=self.get_encoded_id(), - ) + invocation = self.galaxy_invocation def job_detail(steps): param_keys_to_remove = { @@ -460,48 +481,56 @@ class GalaxyWorkflowInvocation(models.Model): "chromInfo", "dbkey", } - for step in invocation["steps"]: - if step["job_id"] is not None: - job = gi.jobs.show_job(step["job_id"], full_details=True) - tool = gi.tools.show_tool(job["tool_id"], io_details=True) - metrics = job["job_metrics"] if "job_metrics" in job else [] - yield ( - { - "order_index": step["order_index"], - "job_id": step["job_id"], - "step_id": step["order_index"], - "tool": tool, - "job": { - "create_time": job["create_time"], - "update_time": job["update_time"], - "metrics": metrics, - "state": job["state"], - "params": dict( - [ - (key, json.loads(param)) - for (key, param) in job["params"].items() - if key not in param_keys_to_remove - ] - ), - }, - } - ) - - return { - "invocation": invocation, - "steps": list(job_detail(invocation["steps"])), - } + if invocation is not None: + for step in invocation["steps"]: + if step["job_id"] is not None: + job = gi.jobs.show_job(step["job_id"], full_details=True) + tool = gi.tools.show_tool(job["tool_id"], io_details=True) + metrics = job["job_metrics"] if "job_metrics" in job else [] + yield ( + { + "order_index": step["order_index"], + "job_id": step["job_id"], + "step_id": step["order_index"], + "tool": tool, + "job": { + "create_time": job["create_time"], + "update_time": job["update_time"], + "metrics": metrics, + "state": job["state"], + "params": dict( + [ + (key, json.loads(param)) + for (key, param) in job["params"].items() + if key not in param_keys_to_remove + ] + ), + }, + } + ) + + if invocation is not None: + return { + "invocation": invocation, + "steps": list(job_detail(invocation["steps"])), + } + else: + return None def get_workflow_job_parameters(self): invocation = self.get_galaxy_invocation() def job_detail(steps): - for step in invocation["steps"]: - if step["job"]["params"] is not None: - # job = gi.jobs.show_job(step["job_id"]) - yield (step["order_index"], step["job"]["params"]) - - return dict(job_detail(invocation["steps"])) + if invocation is not None: + for step in invocation["steps"]: + if step["job"]["params"] is not None: + # job = gi.jobs.show_job(step["job_id"]) + yield (step["order_index"], step["job"]["params"]) + + if invocation is not None: + return dict(job_detail(invocation["steps"])) + else: + return None class GalaxyDataset(models.Model):