import React from 'react'; import { formatDistanceToNow } from 'date-fns'; import superagent from 'superagent'; import ExperimentalWrapper from './ExperimentalWrapper.jsx'; import { Table, Label, Header, Icon, Segment, Message } from 'semantic-ui-react'; function formatDuration(ms) { const seconds = Math.floor(ms / 1000); if (seconds < 60) return `${seconds}s`; const minutes = Math.floor(seconds / 60); const remainingSeconds = seconds % 60; if (minutes < 60) return `${minutes}m ${remainingSeconds}s`; const hours = Math.floor(minutes / 60); const remainingMinutes = minutes % 60; return `${hours}h ${remainingMinutes}m`; } function statusColor(status) { if (status === 'running') return 'green'; if (status === 'completed') return 'blue'; if (status === 'failed') return 'red'; return 'grey'; } export default class WorkerStatus extends React.Component { constructor(props) { super(props); this.state = { workers: [], loading: true, error: null, }; } componentDidMount() { this.fetchWorkers(); this.pollInterval = setInterval(() => this.fetchWorkers(), 5000); this.tickInterval = setInterval(() => this.forceUpdate(), 1000); } componentWillUnmount() { clearInterval(this.pollInterval); clearInterval(this.tickInterval); } fetchWorkers() { superagent.get('/api/admin/workers/status') .then(res => { this.setState({ workers: res.body.workers || [], loading: false, error: null }); }) .catch(err => { this.setState({ error: err.message, loading: false }); }); } render() { const { workers, loading, error } = this.state; return (
Worker Status Live view of active and recently completed workers. Auto-refreshes every 5 seconds.
{error && ( Error fetching worker status

{error}

)} {!loading && workers.length === 0 && !error && ( No active workers

There are no active or recently completed workers at this time.

)} {workers.length > 0 && ( Name Started By Started At Duration Status {workers.map((worker, index) => { const startedAt = new Date(worker.startedAt); const fromNow = formatDistanceToNow(startedAt, { addSuffix: true }); const duration = worker.status === 'running' ? Date.now() - startedAt.getTime() : worker.durationMs; return ( {worker.name} {worker.startedBy} {fromNow} {formatDuration(duration)} ); })}
)}
); } }