Add job cancellation handling and periodic cleanup logic
Introduce new statuses, "to_cancel" and "cancelled", to improve job state tracking. Implement logic to nullify `slurm_id` for cancelled jobs and a background thread to clean up cancelled jobs older than 2 hours. Ensure periodic cleanup runs hourly to maintain database hygiene.
This commit is contained in:
@ -1,9 +1,16 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import React, { useEffect, useState, useRef } from 'react';
|
||||
import { DataGridPremium, GridColDef } from '@mui/x-data-grid-premium';
|
||||
import RunDetails from './RunDetails';
|
||||
import './SampleImage.css';
|
||||
import './ResultGrid.css';
|
||||
import { OpenAPI, SamplesService } from '../../openapi';
|
||||
import CheckCircleIcon from '@mui/icons-material/CheckCircle';
|
||||
import CancelIcon from '@mui/icons-material/Cancel';
|
||||
import AutorenewIcon from '@mui/icons-material/Autorenew';
|
||||
import HourglassEmptyIcon from '@mui/icons-material/HourglassEmpty';
|
||||
import RemoveCircleOutlineIcon from '@mui/icons-material/RemoveCircleOutline';
|
||||
// import ErrorIcon from '@mui/icons-material/Error';
|
||||
// import AccessTimeIcon from '@mui/icons-material/AccessTime';
|
||||
|
||||
|
||||
// Extend your image info interface if needed.
|
||||
@ -101,11 +108,57 @@ interface ResultGridProps {
|
||||
activePgroup: string;
|
||||
}
|
||||
|
||||
const useJobStream = (onJobs: (jobs: any[]) => void) => {
|
||||
const eventSourceRef = useRef<EventSource | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
eventSourceRef.current = new EventSource(`${OpenAPI.BASE}/processing/jobs/stream`);
|
||||
eventSourceRef.current.onmessage = (event) => {
|
||||
// Receives: data: [{job_id, run_id, status, ...}, ...]
|
||||
const jobs = JSON.parse(event.data);
|
||||
onJobs(jobs);
|
||||
};
|
||||
|
||||
return () => {
|
||||
if (eventSourceRef.current) {
|
||||
eventSourceRef.current.close();
|
||||
}
|
||||
};
|
||||
}, [onJobs]);
|
||||
};
|
||||
|
||||
|
||||
const ResultGrid: React.FC<ResultGridProps> = ({ activePgroup }) => {
|
||||
const [rows, setRows] = useState<TreeRow[]>([]);
|
||||
const [basePath, setBasePath] = useState('');
|
||||
const [detailPanelHeights, setDetailPanelHeights] = useState<{ [key: string]: number }>({}); // Store dynamic heights
|
||||
const [jobStatusMap, setJobStatusMap] = useState<{ [runId: number]: string }>({});
|
||||
|
||||
const getStatusIcon = (status: string) => {
|
||||
switch (status) {
|
||||
case 'todo':
|
||||
return <HourglassEmptyIcon color="action" titleAccess="Todo" />;
|
||||
case 'submitted':
|
||||
return <AutorenewIcon color="primary" className="spin" titleAccess="Submitted" />;
|
||||
case 'completed':
|
||||
return <CheckCircleIcon color="success" titleAccess="Completed" />;
|
||||
case 'failed':
|
||||
return <CancelIcon color="error" titleAccess="Failed" />;
|
||||
case 'no job':
|
||||
default:
|
||||
return <RemoveCircleOutlineIcon color="disabled" titleAccess="No job" />;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
useJobStream((jobs) => {
|
||||
const map: { [runId: number]: string } = {};
|
||||
for (const job of jobs) {
|
||||
// Map job status by run_id (or job_id as preferred)
|
||||
map[job.run_id] = job.status;
|
||||
}
|
||||
setJobStatusMap(map);
|
||||
});
|
||||
|
||||
const hasProcessingResults = (row: TreeRow): boolean => {
|
||||
// You can later replace this placeholder with actual logic.
|
||||
@ -238,6 +291,15 @@ const ResultGrid: React.FC<ResultGridProps> = ({ activePgroup }) => {
|
||||
headerName: 'Sample Name',
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
field: 'jobStatus',
|
||||
headerName: 'Job Status',
|
||||
width: 120,
|
||||
renderCell: (params) =>
|
||||
params.row.type === 'run'
|
||||
? getStatusIcon(jobStatusMap[params.row.experimentId] || 'no job')
|
||||
: null,
|
||||
},
|
||||
{
|
||||
field: 'puck_name',
|
||||
headerName: 'Puck Name',
|
||||
|
Reference in New Issue
Block a user