Skip to content
This repository has been archived by the owner on Mar 19, 2024. It is now read-only.

New frontend/bugfix/show logs directly when task fails #217

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions new-frontend/src/app/helpers/task.helper.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { TranslateService } from '@ngx-translate/core';
import { Task, TaskStatus } from '../models/api/task.models';
import { Task, TaskStatus, TaskStatusGroup } from '../models/api/task.models';

export const getChipTypeForStatus = (status: TaskStatus): 'default' | 'active' | 'success' | 'error' => {
switch (status) {
Expand Down Expand Up @@ -29,21 +29,21 @@ export const getTaskStatusTranslation = (translateService: TranslateService, sta
return translation;
};

export const getStatusInfoTypeForStatus = (status: TaskStatus): 'pending' | 'active' | 'success' | 'error' => {
export const getStatusType = (status: TaskStatus): TaskStatusGroup => {
switch (status) {
case TaskStatus.Initializing:
case TaskStatus.Active:
return 'active';
return TaskStatusGroup.Active;
case TaskStatus.Completed:
return 'success';
return TaskStatusGroup.Success;
case TaskStatus.Failed:
case TaskStatus.StartFailed:
case TaskStatus.NoDockerImage:
case TaskStatus.Crashed:
case TaskStatus.Killed:
return 'error';
return TaskStatusGroup.Error;
default:
return 'pending';
return TaskStatusGroup.Pending;
}
};

Expand Down
7 changes: 7 additions & 0 deletions new-frontend/src/app/models/api/task.models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@ export enum TaskStatus {
Killed = 'killed by user'
}

export enum TaskStatusGroup {
Pending = 'pending',
Active = 'active',
Success = 'success',
Error = 'error'
}

export interface GetTaskParameters {
collaboration_id?: string;
init_user_id?: string;
Expand Down
6 changes: 3 additions & 3 deletions new-frontend/src/app/pages/task/read/task-read.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@
</mat-menu>
</app-page-header>
<ng-container *ngIf="!isLoading && task; else loading">
<mat-card *ngIf="isTaskInProgress()">
<mat-card *ngIf="isTaskNotComplete()">
<mat-card-header>
<mat-card-title>{{ "task-read.card-status.title" | translate }}</mat-card-title>
</mat-card-header>
<mat-card-content>
<div class="status-info-container">
<app-status-info
*ngFor="let run of task?.runs"
[type]="getStatusInfoTypeForStatus(run.status)"
[type]="getStatusType(run.status)"
title="{{ run.node.name }}"
[subTitle]="getTaskStatusTranslation(run.status)"
>
Expand All @@ -43,7 +43,7 @@
<div class="status-info-container" *ngFor="let childTask of childTasks">
<app-status-info
*ngFor="let run of childTask?.runs"
[type]="getStatusInfoTypeForStatus(run.status)"
[type]="getStatusType(run.status)"
title="{{ run.node.name }}"
[subTitle]="getTaskStatusTranslation(run.status)"
>
Expand Down
40 changes: 30 additions & 10 deletions new-frontend/src/app/pages/task/read/task-read.component.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Component, HostBinding, Input, OnDestroy, OnInit } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
import { getChipTypeForStatus, getStatusInfoTypeForStatus, getTaskStatusTranslation } from 'src/app/helpers/task.helper';
import { getChipTypeForStatus, getStatusType, getTaskStatusTranslation } from 'src/app/helpers/task.helper';
import { Algorithm, AlgorithmFunction, Output } from 'src/app/models/api/algorithm.model';
import { Task, TaskLazyProperties, TaskRun, TaskStatus, TaskResult, BaseTask } from 'src/app/models/api/task.models';
import { Task, TaskLazyProperties, TaskRun, TaskStatus, TaskResult, BaseTask, TaskStatusGroup } from 'src/app/models/api/task.models';
import { routePaths } from 'src/app/routes';
import { AlgorithmService } from 'src/app/services/algorithm.service';
import { TaskService } from 'src/app/services/task.service';
Expand Down Expand Up @@ -140,15 +140,15 @@ export class TaskReadComponent implements OnInit, OnDestroy {
return getTaskStatusTranslation(this.translateService, status);
}

getStatusInfoTypeForStatus(status: TaskStatus) {
return getStatusInfoTypeForStatus(status);
getStatusType(status: TaskStatus) {
return getStatusType(status);
}

async getChildTasks(): Promise<BaseTask[]> {
return await this.taskService.getTasks(1, { parent_id: this.task?.id, include: 'results,runs' }).then((data) => data.data);
}

isTaskInProgress(): boolean {
isTaskNotComplete(): boolean {
if (!this.task) return false;
if (this.task.runs.length <= 0) return false;
if (this.task.results?.some((result) => result.result === null)) return true;
Expand Down Expand Up @@ -280,16 +280,36 @@ export class TaskReadComponent implements OnInit, OnDestroy {
run.status = statusUpdate.status as TaskStatus;
}

// if the task is completed, we need to reload the task to get the results
if (statusUpdate.status === TaskStatus.Completed) {
// Task is completed but we need to wait for the results to be available
// if all task runs are completed, update the status of the task itself
if (this.task.runs.every((r) => r.status === TaskStatus.Completed)) {
this.task.status = TaskStatus.Completed;
} else if (this.task.runs.some((r) => getStatusType(r.status) === TaskStatusGroup.Error)) {
this.task.status = TaskStatus.Failed;
}

// if the task is completed, we need to reload the task to get the results.
// Also, if the task crashes, we should reload the task to get the logs.
if ([TaskStatusGroup.Error, TaskStatusGroup.Success].includes(getStatusType(statusUpdate.status as TaskStatus))) {
// Task is no longer running but we need to wait for the results to be available
// on the server. Poll every second until the results are available.
timer(0, 1000)
.pipe(takeUntil(this.waitTaskComplete$))
.subscribe({
next: async () => {
this.task = await this.getMainTask();
if (!this.isTaskInProgress()) {
if (!this.task) return;
const renewed_task = await this.getMainTask();
// keep statuses of the task and the runs - these are updated by the socket
// and are likely more up-to-date than the statuses at the central server
renewed_task.status = this.task.status;
renewed_task.runs.map((run) => {
const old_run = this.task?.runs.find((r) => r.id === run.id);
if (old_run) {
run.status = old_run.status;
}
});
this.task = renewed_task;
if (!this.isTaskNotComplete() || getStatusType(this.task.status) === TaskStatusGroup.Error) {
this.childTasks = await this.getChildTasks();
this.initData(false);
// stop polling
this.waitTaskComplete$.next(true);
Expand Down