Skip to content
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
20 changes: 3 additions & 17 deletions beanstalk_worker/__init__.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
import traceback

from functools import wraps
from logging import getLogger

import sentry_sdk

from django.utils import timezone
from lazy_services import LazyService # type: ignore


Expand All @@ -21,7 +18,8 @@ def inner_task(func):

@wraps(func)
def wrapper(*args, **kwargs):
from iaso.models.base import ERRORED, RUNNING, KilledException, Project, Task
from iaso.models.base import RUNNING, KilledException, Project
from iaso.models.task import Task

immediate = kwargs.pop("_immediate", False) # if true, we need to run the task now, we are a worker
if immediate:
Expand All @@ -39,19 +37,7 @@ def wrapper(*args, **kwargs):
# If it was interrupted in the middle of a transaction the new status was not saved so save it again
the_task.save()
except Exception as e:
the_task.status = ERRORED
the_task.ended_at = timezone.now()
the_task.result = {
"result": ERRORED,
"message": str(e),
"stack_trace": traceback.format_exc(),
"last_progress_message": the_task.progress_message,
}
the_task.progress_message = e.message if hasattr(e, "message") else str(e)
# Extra debug info
if hasattr(e, "extra"):
the_task.result["extra"] = e.extra
the_task.save()
the_task.report_failure(e)
logger.exception(f"Error when running task {the_task.id}: {the_task}")
sentry_sdk.capture_exception(e)
return the_task
Expand Down
2 changes: 1 addition & 1 deletion beanstalk_worker/management/commands/run_task.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from django.core.management.base import BaseCommand

from beanstalk_worker import task_service
from iaso.models.base import Task
from iaso.models.task import Task


class Command(BaseCommand):
Expand Down
3 changes: 2 additions & 1 deletion beanstalk_worker/services.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
from django.db import connection
from django.utils import timezone

from iaso.models.base import KILLED, QUEUED, RUNNING, Task
from iaso.models.base import KILLED, QUEUED, RUNNING
from iaso.models.task import Task


logger = getLogger(__name__)
Expand Down
3 changes: 2 additions & 1 deletion beanstalk_worker/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
from django.utils import timezone
from django.views.decorators.csrf import csrf_exempt

from iaso.models.base import QUEUED, RUNNING, Task
from iaso.models.base import QUEUED, RUNNING
from iaso.models.task import Task

from . import task_service

Expand Down
6 changes: 5 additions & 1 deletion entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,10 @@ case "$1" in
python "${@:2}"
;;
* )
show_help
if [[ $2 == /opt/.pycharm_helpers/* ]]; then
${@}
else
show_help
fi
;;
esac
2 changes: 2 additions & 0 deletions hat/assets/js/apps/Iaso/domains/app/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -813,6 +813,7 @@
"iaso.label.submissionsLocations": "Submissions locations",
"iaso.label.submitter": "Submitter",
"iaso.label.submitterTeam": "Submitter team",
"iaso.label.task": "Task",
"iaso.label.tasks": "Tasks",
"iaso.label.team": "Team",
"iaso.label.teams": "Teams",
Expand Down Expand Up @@ -1513,6 +1514,7 @@
"iaso.tasks.last_launch_by": "Last launch:",
"iaso.tasks.message": "Message",
"iaso.tasks.name": "Name",
"iaso.tasks.no_logs_to_show": "No logs to show.",
"iaso.tasks.polioNotificationImport.details": "Polio Notifications Import Details",
"iaso.tasks.polioNotificationImport.errors": "{count} error(s). The following data couldn't be imported.",
"iaso.tasks.progress": "Progress",
Expand Down
4 changes: 3 additions & 1 deletion hat/assets/js/apps/Iaso/domains/app/translations/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -767,6 +767,7 @@
"iaso.label.submissionsLocations": "Submissions locations",
"iaso.label.submitter": "Submitter",
"iaso.label.submitterTeam": "Submitter team",
"iaso.label.tasks": "Task",
"iaso.label.tasks": "Tasks",
"iaso.label.team": "Team",
"iaso.label.teams": "Teams",
Expand Down Expand Up @@ -1213,5 +1214,6 @@
"iaso.projets.featureflag.mobile_check_ou_update": "Móvil: Advertir al usuario cuando las unidades organizativas han sido actualizadas",
"iaso.projets.featureflag.mobile_entity_limited_search": "Móvil: Limitar búsqueda de entidades",
"iaso.projets.featureflag.mobile_entity_no_creation": "Móvil: El usuario no puede crear una entidad",
"iaso.snackBar.deleteEntityTypeError": "Se ha producido un error al eliminar un tipo de entidad"
"iaso.snackBar.deleteEntityTypeError": "Se ha producido un error al eliminar un tipo de entidad",
"iaso.tasks.no_logs_to_show": "No hay registros para mostrar."
}
2 changes: 2 additions & 0 deletions hat/assets/js/apps/Iaso/domains/app/translations/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -813,6 +813,7 @@
"iaso.label.submissionsLocations": "Emplacements des soumissions",
"iaso.label.submitter": "Soumis par",
"iaso.label.submitterTeam": "Equipe d'origine",
"iaso.label.task": "Tâche",
"iaso.label.tasks": "Tâches",
"iaso.label.team": "Equipe",
"iaso.label.teams": "Equipes",
Expand Down Expand Up @@ -1514,6 +1515,7 @@
"iaso.tasks.last_launch_by": "Dernière exécution :",
"iaso.tasks.message": "Message",
"iaso.tasks.name": "Nom",
"iaso.tasks.no_logs_to_show": "Aucun journal à afficher.",
"iaso.tasks.polioNotificationImport.details": "Détails de l'importation des notifications Polio",
"iaso.tasks.polioNotificationImport.errors": "{count} erreur(s). L'import des données suivantes a échoué.",
"iaso.tasks.progress": "Avancement",
Expand Down
62 changes: 62 additions & 0 deletions hat/assets/js/apps/Iaso/domains/tasks/components/ActionCell.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import React, { FunctionComponent } from 'react';
import ReplayIcon from '@mui/icons-material/Replay';
import { IconButton, useSafeIntl } from 'bluesquare-components';
import { NotificationImportDetailModal } from 'Iaso/domains/tasks/components/NotificationImportDetailModal';
import { TaskLogsModal } from 'Iaso/domains/tasks/components/TaskLogsModal';
import { useKillTask, useRelaunchTask } from 'Iaso/domains/tasks/hooks/api';
import MESSAGES from 'Iaso/domains/tasks/messages';
import { Task } from 'Iaso/domains/tasks/types';
import { userHasPermission } from 'Iaso/domains/users/utils';
import { POLIO_NOTIFICATIONS } from 'Iaso/utils/permissions';
import { useCurrentUser } from 'Iaso/utils/usersUtils';

export type Props = {
task: Task<any>;
};

export const TaskActionCell: FunctionComponent<Props> = ({ task }) => {
const { formatMessage } = useSafeIntl();
const hasPolioNotificationsPerm = userHasPermission(
POLIO_NOTIFICATIONS,
useCurrentUser(),
);
const { mutateAsync: killTaskAction } = useKillTask();
const { mutateAsync: relaunchTaskAction } = useRelaunchTask();
return (
<section>
{['QUEUED', 'RUNNING', 'UNKNOWN'].includes(task.status) &&
!task.should_be_killed && (
<IconButton
onClick={() =>
killTaskAction({
id: task.id,
should_be_killed: true,
})
}
icon="stop"
tooltipMessage={MESSAGES.killTask}
/>
)}
{task.status === 'ERRORED' && (
<IconButton
onClick={() =>
relaunchTaskAction({
id: task.id,
})
}
overrideIcon={ReplayIcon}
tooltipMessage={MESSAGES.relaunch}
/>
)}
{task.should_be_killed &&
task.status === 'RUNNING' &&
formatMessage(MESSAGES.killSignalSent)}
{hasPolioNotificationsPerm &&
['SUCCESS', 'ERRORED'].includes(task.status) &&
task.name === 'create_polio_notifications_async' && (
<NotificationImportDetailModal task={task} iconProps={{}} />
)}
<TaskLogsModal task={task} iconProps={{}} />
</section>
);
};
73 changes: 73 additions & 0 deletions hat/assets/js/apps/Iaso/domains/tasks/components/StatusCell.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import React, { FunctionComponent } from 'react';
import { Chip } from '@mui/material';
import { useSafeIntl } from 'bluesquare-components';
import MESSAGES from 'Iaso/domains/tasks/messages';
import { Task } from 'Iaso/domains/tasks/types';
import { SxStyles } from 'Iaso/types/general';

export type Props = {
task: Task<any>;
};

const getTranslatedStatusMessage = (
formatMessage: (record: Record<string, string>) => string,
status: string,
): string => {
// Return untranslated status if not translation available
return MESSAGES[status.toLowerCase()]
? formatMessage(MESSAGES[status.toLowerCase()])
: status;
};

const getStatusColor = (
status: string,
): 'info' | 'success' | 'error' | 'warning' => {
if (['QUEUED', 'RUNNING'].includes(status)) {
return 'info';
}
if (['EXPORTED', 'SUCCESS'].includes(status)) {
return 'success';
}
if (status === 'ERRORED') {
return 'error';
}
return 'warning';
};

const safePercent = (a: number, b: number): string => {
if (b === 0) {
return '';
}
const percent = 100 * (a / b);
return `${percent.toFixed(2)}%`;
};

const styles: SxStyles = {
chip: {
color: 'white',
},
};

export const StatusCell: FunctionComponent<Props> = ({ task }) => {
const { formatMessage } = useSafeIntl();
return (
<span>
{task.status === 'RUNNING' && task.end_value > 0 ? (
`${task.progress_value}/${task.end_value} (${safePercent(
task.progress_value,
task.end_value,
)})`
) : (
<Chip
label={getTranslatedStatusMessage(
formatMessage,
task.status,
)}
color={getStatusColor(task.status)}
size="small"
sx={styles.chip}
/>
)}
</span>
);
};
73 changes: 73 additions & 0 deletions hat/assets/js/apps/Iaso/domains/tasks/components/TaskBaseInfo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import React, { FunctionComponent, ReactNode } from 'react';
import { Table, TableBody, TableRow, TableCell } from '@mui/material';
import { TablePropsSizeOverrides } from '@mui/material/Table/Table';
import { makeStyles } from '@mui/styles';
import { OverridableStringUnion } from '@mui/types/esm';
import { useSafeIntl } from 'bluesquare-components';

import moment from 'moment';
import { StatusCell } from 'Iaso/domains/tasks/components/StatusCell';
import getDisplayName from 'Iaso/utils/usersUtils';
import MESSAGES from '../messages';

import { Task } from '../types';

const useStyles = makeStyles(theme => ({
leftCell: {
// @ts-ignore
borderRight: `1px solid ${theme.palette.ligthGray.border}`,
fontWeight: 'bold',
},
}));

type RowProps = {
label: string;
value?: string | ReactNode;
};

const Row: FunctionComponent<RowProps> = ({ label, value }) => {
const classes = useStyles();
return (
<TableRow>
<TableCell className={classes.leftCell}>{label}</TableCell>
<TableCell>{value}</TableCell>
</TableRow>
);
};

type Props = {
task: Task<any>;
size?: OverridableStringUnion<'small' | 'medium', TablePropsSizeOverrides>;
};
export const TaskBaseInfo: FunctionComponent<Props> = ({ task, size }) => {
const { formatMessage } = useSafeIntl();
return (
<Table size={size} data-test="task-base-info">
<TableBody>
<Row label={formatMessage(MESSAGES.name)} value={task.name} />
<Row
label={formatMessage(MESSAGES.user)}
value={getDisplayName(task.launcher)}
/>
<Row
label={formatMessage(MESSAGES.timeCreated)}
value={moment.unix(task.created_at).format('LTS')}
/>
<Row
label={formatMessage(MESSAGES.timeStart)}
value={moment.unix(task.started_at).format('LTS')}
/>
{task.ended_at && (
<Row
label={formatMessage(MESSAGES.timeEnd)}
value={moment.unix(task.ended_at).format('LTS')}
/>
)}
<Row
label={formatMessage(MESSAGES.status)}
value={task ? <StatusCell task={task} /> : ''}
/>
</TableBody>
</Table>
);
};
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { defineMessages } from 'react-intl';
import React, { FunctionComponent } from 'react';
import { useQuery } from 'react-query';
import { Button, Container } from '@mui/material';
import { useSafeIntl } from 'bluesquare-components';
import { defineMessages } from 'react-intl';
import { useQuery } from 'react-query';
// @ts-ignore
import { Task } from 'Iaso/domains/tasks/types';
// @ts-ignore
Expand All @@ -25,7 +25,7 @@ const MESSAGES = defineMessages({
});

type Props = {
task: Task;
task: Task<any>;
};

const TaskDetails: FunctionComponent<Props> = ({ task }) => {
Expand Down
Loading
Loading