Add test for executor

This commit is contained in:
2025-11-11 02:15:57 +07:00
parent d02a07f86b
commit e8e2ec5a43
18 changed files with 81418 additions and 170 deletions

View File

@@ -13,13 +13,13 @@ const JobsSettings: React.FC = () => {
const [pageSize, setPageSize] = useState(50)
const [sortBy, setSortBy] = useState<string>('CreatedAt')
const [sortOrder, setSortOrder] = useState<string>('desc')
const [statusFilter, setStatusFilter] = useState<string>('Pending')
const [statusFilter, setStatusFilter] = useState<string>('Failed')
const [jobTypeFilter, setJobTypeFilter] = useState<string>('')
const [userIdFilter, setUserIdFilter] = useState<string>('')
const [workerIdFilter, setWorkerIdFilter] = useState<string>('')
const [bundleRequestIdFilter, setBundleRequestIdFilter] = useState<string>('')
const [filtersOpen, setFiltersOpen] = useState<boolean>(false)
const [showTable, setShowTable] = useState<boolean>(false)
const [showTable, setShowTable] = useState<boolean>(true)
const jobClient = new JobClient({}, apiUrl)
const queryClient = useQueryClient()
@@ -146,7 +146,7 @@ const JobsSettings: React.FC = () => {
}
const clearFilters = () => {
setStatusFilter('Pending') // Reset to Pending instead of All
setStatusFilter('Failed') // Reset to Failed instead of All
setJobTypeFilter('')
setUserIdFilter('')
setWorkerIdFilter('')
@@ -378,50 +378,15 @@ const JobsSettings: React.FC = () => {
)}
</div>
{/* Load Table Button */}
{!showTable && (
<div className="card bg-base-100 shadow-md mb-4">
<div className="card-body">
<div className="flex items-center justify-between">
<div>
<h3 className="card-title text-lg">Jobs List</h3>
<p className="text-sm text-base-content/70">Click the button below to load and view the jobs table</p>
</div>
<button
className="btn btn-primary"
onClick={() => setShowTable(true)}
>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth="1.5" stroke="currentColor" className="w-5 h-5">
<path strokeLinecap="round" strokeLinejoin="round" d="M3.75 3v11.25A2.25 2.25 0 006 16.5h2.25M3.75 3h-1.5m1.5 0h16.5m0 0h1.5m-1.5 0v11.25A2.25 2.25 0 0118 16.5h-2.25m-7.5 0h7.5m-7.5 0l-1 3m8.5-3l1 3m0 0l.5 1.5m-.5-1.5h-9.5m0 0l-.5 1.5M9 11.25v1.5M12 9v3.75m3-3.75v3.75m-9 .75h12.75a2.25 2.25 0 002.25-2.25V6.75a2.25 2.25 0 00-2.25-2.25H6.75A2.25 2.25 0 004.5 6.75v7.5a2.25 2.25 0 002.25 2.25z" />
</svg>
Load Jobs Table
</button>
</div>
</div>
{/* Jobs List Header */}
<div className="card bg-base-100 shadow-md mb-4">
<div className="card-body py-3">
<h3 className="card-title text-lg">Jobs List</h3>
</div>
)}
</div>
{showTable && (
<>
{/* Hide Table Button */}
<div className="card bg-base-100 shadow-md mb-4">
<div className="card-body py-3">
<div className="flex items-center justify-between">
<h3 className="card-title text-lg">Jobs List</h3>
<button
className="btn btn-ghost btn-sm"
onClick={() => setShowTable(false)}
>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth="1.5" stroke="currentColor" className="w-5 h-5">
<path strokeLinecap="round" strokeLinejoin="round" d="M6 18L18 6M6 6l12 12" />
</svg>
Hide Table
</button>
</div>
</div>
</div>
{filtersOpen && (
{filtersOpen && (
<div className="card bg-base-200 mb-4">
<div className="card-body">
<div className="grid grid-cols-1 md:grid-cols-3 lg:grid-cols-5 gap-4">
@@ -527,28 +492,25 @@ const JobsSettings: React.FC = () => {
</div>
)}
<JobsTable
jobs={jobs}
isLoading={isLoading}
currentPage={currentPage}
totalPages={totalPages}
totalCount={totalCount}
pageSize={pageSize}
sortBy={sortBy}
sortOrder={sortOrder}
onPageChange={handlePageChange}
onSortChange={handleSortChange}
onRetryJob={handleRetryJob}
isRetrying={retryJobMutation.isPending}
onDeleteJob={handleDeleteJob}
isDeleting={deleteJobMutation.isPending}
/>
</>
)}
<JobsTable
jobs={jobs}
isLoading={isLoading}
currentPage={currentPage}
totalPages={totalPages}
totalCount={totalCount}
pageSize={pageSize}
sortBy={sortBy}
sortOrder={sortOrder}
onPageChange={handlePageChange}
onSortChange={handleSortChange}
onRetryJob={handleRetryJob}
isRetrying={retryJobMutation.isPending}
onDeleteJob={handleDeleteJob}
isDeleting={deleteJobMutation.isPending}
/>
{/* Bottom Menu Bar */}
{showTable && (
<BottomMenuBar>
<BottomMenuBar>
<li>
<a
onClick={(e) => {

View File

@@ -149,22 +149,54 @@ const JobsTable: React.FC<IJobsTable> = ({
),
},
{
Header: () => <SortableHeader column="CreatedAt" label="Created" />,
Header: () => <SortableHeader column="CreatedAt" label="Timeline" />,
accessor: 'createdAt',
width: 180,
Cell: ({ value }: any) => formatDate(value),
},
{
Header: () => <SortableHeader column="StartedAt" label="Started" />,
accessor: 'startedAt',
width: 180,
Cell: ({ value }: any) => formatDate(value),
},
{
Header: () => <SortableHeader column="CompletedAt" label="Completed" />,
accessor: 'completedAt',
width: 180,
Cell: ({ value }: any) => formatDate(value),
width: 220,
Cell: ({ row }: any) => {
const createdAt = row.original.createdAt
const startedAt = row.original.startedAt
const completedAt = row.original.completedAt
// Calculate duration between started and completed
const calculateDuration = (start: Date | string | null, end: Date | string | null) => {
if (!start || !end) return null
try {
const startDate = new Date(start)
const endDate = new Date(end)
const diffMs = endDate.getTime() - startDate.getTime()
// Convert to human readable format
const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24))
const diffHours = Math.floor((diffMs % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60))
const diffMinutes = Math.floor((diffMs % (1000 * 60 * 60)) / (1000 * 60))
const diffSeconds = Math.floor((diffMs % (1000 * 60)) / 1000)
if (diffDays > 0) return `${diffDays}d ${diffHours}h ${diffMinutes}m`
if (diffHours > 0) return `${diffHours}h ${diffMinutes}m ${diffSeconds}s`
if (diffMinutes > 0) return `${diffMinutes}m ${diffSeconds}s`
return `${diffSeconds}s`
} catch {
return null
}
}
const duration = calculateDuration(startedAt, completedAt)
return (
<div className="flex flex-col gap-1 text-xs">
<div className="flex flex-col gap-0.5">
<div className="text-gray-500">Created: {formatDate(createdAt)}</div>
<div className="text-blue-500">Started: {formatDate(startedAt)}</div>
<div className="text-green-500">Completed: {formatDate(completedAt)}</div>
</div>
{duration && (
<div className="text-purple-500 font-semibold">
Duration: {duration}
</div>
)}
</div>
)
},
},
{
Header: 'Error Message',