cancelling actions works now
This commit is contained in:
@@ -32,7 +32,7 @@ export type ApiResponse_ExecutionResponse = {
|
||||
*/
|
||||
enforcement?: number | null;
|
||||
/**
|
||||
* Executor ID (worker/executor that ran this)
|
||||
* Identity ID that initiated this execution
|
||||
*/
|
||||
executor?: number | null;
|
||||
/**
|
||||
@@ -43,6 +43,10 @@ export type ApiResponse_ExecutionResponse = {
|
||||
* Parent execution ID (for nested/child executions)
|
||||
*/
|
||||
parent?: number | null;
|
||||
/**
|
||||
* Worker ID currently assigned to this execution
|
||||
*/
|
||||
worker?: number | null;
|
||||
/**
|
||||
* Execution result/output
|
||||
*/
|
||||
|
||||
@@ -28,7 +28,7 @@ export type ExecutionResponse = {
|
||||
*/
|
||||
enforcement?: number | null;
|
||||
/**
|
||||
* Executor ID (worker/executor that ran this)
|
||||
* Identity ID that initiated this execution
|
||||
*/
|
||||
executor?: number | null;
|
||||
/**
|
||||
@@ -39,6 +39,10 @@ export type ExecutionResponse = {
|
||||
* Parent execution ID (for nested/child executions)
|
||||
*/
|
||||
parent?: number | null;
|
||||
/**
|
||||
* Worker ID currently assigned to this execution
|
||||
*/
|
||||
worker?: number | null;
|
||||
/**
|
||||
* Execution result/output
|
||||
*/
|
||||
|
||||
@@ -224,7 +224,7 @@ export class ExecutionsService {
|
||||
*/
|
||||
enforcement?: number | null;
|
||||
/**
|
||||
* Executor ID (worker/executor that ran this)
|
||||
* Identity ID that initiated this execution
|
||||
*/
|
||||
executor?: number | null;
|
||||
/**
|
||||
@@ -235,6 +235,10 @@ export class ExecutionsService {
|
||||
* Parent execution ID (for nested/child executions)
|
||||
*/
|
||||
parent?: number | null;
|
||||
/**
|
||||
* Worker ID currently assigned to this execution
|
||||
*/
|
||||
worker?: number | null;
|
||||
/**
|
||||
* Execution result/output
|
||||
*/
|
||||
|
||||
@@ -337,11 +337,16 @@ function TextFileDetail({
|
||||
|
||||
interface ProgressDetailProps {
|
||||
artifactId: number;
|
||||
isRunning?: boolean;
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
function ProgressDetail({ artifactId, onClose }: ProgressDetailProps) {
|
||||
const { data: artifactData, isLoading } = useArtifact(artifactId);
|
||||
function ProgressDetail({
|
||||
artifactId,
|
||||
isRunning = false,
|
||||
onClose,
|
||||
}: ProgressDetailProps) {
|
||||
const { data: artifactData, isLoading } = useArtifact(artifactId, isRunning);
|
||||
const artifact = artifactData?.data;
|
||||
|
||||
const progressEntries = useMemo(() => {
|
||||
@@ -707,6 +712,7 @@ export default function ExecutionArtifactsPanel({
|
||||
<div className="px-3">
|
||||
<ProgressDetail
|
||||
artifactId={artifact.id}
|
||||
isRunning={isRunning}
|
||||
onClose={() => setExpandedProgressId(null)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -69,9 +69,10 @@ const ExecutionPreviewPanel = memo(function ExecutionPreviewPanel({
|
||||
execution?.status === "running" ||
|
||||
execution?.status === "scheduling" ||
|
||||
execution?.status === "scheduled" ||
|
||||
execution?.status === "requested";
|
||||
execution?.status === "requested" ||
|
||||
execution?.status === "canceling";
|
||||
|
||||
const isCancellable = isRunning || execution?.status === "canceling";
|
||||
const isCancellable = isRunning;
|
||||
|
||||
const startedAt = execution?.started_at
|
||||
? new Date(execution.started_at)
|
||||
@@ -241,13 +242,23 @@ const ExecutionPreviewPanel = memo(function ExecutionPreviewPanel({
|
||||
{execution.executor && (
|
||||
<div>
|
||||
<dt className="text-xs font-medium text-gray-500 uppercase tracking-wide">
|
||||
Executor
|
||||
Initiated By
|
||||
</dt>
|
||||
<dd className="mt-0.5 text-sm text-gray-900 font-mono">
|
||||
#{execution.executor}
|
||||
</dd>
|
||||
</div>
|
||||
)}
|
||||
{execution.worker && (
|
||||
<div>
|
||||
<dt className="text-xs font-medium text-gray-500 uppercase tracking-wide">
|
||||
Worker
|
||||
</dt>
|
||||
<dd className="mt-0.5 text-sm text-gray-900 font-mono">
|
||||
#{execution.worker}
|
||||
</dd>
|
||||
</div>
|
||||
)}
|
||||
{execution.workflow_task && (
|
||||
<div>
|
||||
<dt className="text-xs font-medium text-gray-500 uppercase tracking-wide">
|
||||
|
||||
@@ -147,15 +147,18 @@ export function useExecutionArtifacts(
|
||||
return response;
|
||||
},
|
||||
enabled: !!executionId,
|
||||
staleTime: isRunning ? 3000 : 10000,
|
||||
refetchInterval: isRunning ? 3000 : 10000,
|
||||
staleTime: isRunning ? 3000 : 30000,
|
||||
refetchInterval: isRunning ? 3000 : false,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch a single artifact by ID (includes data field for progress artifacts).
|
||||
*
|
||||
* @param isRunning - When true, polls every 3s for live updates. When false,
|
||||
* uses a longer stale time and disables automatic polling.
|
||||
*/
|
||||
export function useArtifact(id: number | undefined) {
|
||||
export function useArtifact(id: number | undefined, isRunning = false) {
|
||||
return useQuery({
|
||||
queryKey: ["artifacts", id],
|
||||
queryFn: async () => {
|
||||
@@ -169,8 +172,8 @@ export function useArtifact(id: number | undefined) {
|
||||
return response;
|
||||
},
|
||||
enabled: !!id,
|
||||
staleTime: 3000,
|
||||
refetchInterval: 3000,
|
||||
staleTime: isRunning ? 3000 : 30000,
|
||||
refetchInterval: isRunning ? 3000 : false,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -205,6 +205,11 @@ export function useExecutionStream(options: UseExecutionStreamOptions = {}) {
|
||||
},
|
||||
);
|
||||
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: ["history", "execution", executionNotification.entity_id],
|
||||
exact: false,
|
||||
});
|
||||
|
||||
// Update execution list queries by modifying existing data.
|
||||
// We need to iterate manually to access query keys for filtering.
|
||||
const queries = queryClient
|
||||
|
||||
@@ -22,6 +22,16 @@ interface ExecutionsQueryParams {
|
||||
topLevelOnly?: boolean;
|
||||
}
|
||||
|
||||
function isExecutionActive(status: string | undefined): boolean {
|
||||
return (
|
||||
status === "requested" ||
|
||||
status === "scheduling" ||
|
||||
status === "scheduled" ||
|
||||
status === "running" ||
|
||||
status === "canceling"
|
||||
);
|
||||
}
|
||||
|
||||
export function useExecutions(params?: ExecutionsQueryParams) {
|
||||
// Check if any filters are applied
|
||||
const hasFilters =
|
||||
@@ -67,7 +77,9 @@ export function useExecution(id: number) {
|
||||
return response;
|
||||
},
|
||||
enabled: !!id,
|
||||
staleTime: 30000, // 30 seconds - SSE handles real-time updates
|
||||
staleTime: 30000,
|
||||
refetchInterval: (query) =>
|
||||
isExecutionActive(query.state.data?.data?.status) ? 3000 : false,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -180,11 +192,7 @@ export function useChildExecutions(parentId: number | undefined) {
|
||||
const data = query.state.data;
|
||||
if (!data) return false;
|
||||
const hasActive = data.data.some(
|
||||
(e) =>
|
||||
e.status === "requested" ||
|
||||
e.status === "scheduling" ||
|
||||
e.status === "scheduled" ||
|
||||
e.status === "running",
|
||||
(e) => isExecutionActive(e.status),
|
||||
);
|
||||
return hasActive ? 5000 : false;
|
||||
},
|
||||
|
||||
@@ -199,10 +199,10 @@ export default function ExecutionDetailPage() {
|
||||
execution.status === ExecutionStatus.RUNNING ||
|
||||
execution.status === ExecutionStatus.SCHEDULING ||
|
||||
execution.status === ExecutionStatus.SCHEDULED ||
|
||||
execution.status === ExecutionStatus.REQUESTED;
|
||||
execution.status === ExecutionStatus.REQUESTED ||
|
||||
execution.status === ExecutionStatus.CANCELING;
|
||||
|
||||
const isCancellable =
|
||||
isRunning || execution.status === ExecutionStatus.CANCELING;
|
||||
const isCancellable = isRunning;
|
||||
|
||||
return (
|
||||
<div className="p-6 max-w-7xl mx-auto">
|
||||
@@ -392,13 +392,23 @@ export default function ExecutionDetailPage() {
|
||||
{execution.executor && (
|
||||
<div>
|
||||
<dt className="text-sm font-medium text-gray-500">
|
||||
Executor ID
|
||||
Initiated By
|
||||
</dt>
|
||||
<dd className="mt-1 text-sm text-gray-900">
|
||||
{execution.executor}
|
||||
</dd>
|
||||
</div>
|
||||
)}
|
||||
{execution.worker && (
|
||||
<div>
|
||||
<dt className="text-sm font-medium text-gray-500">
|
||||
Worker ID
|
||||
</dt>
|
||||
<dd className="mt-1 text-sm text-gray-900">
|
||||
{execution.worker}
|
||||
</dd>
|
||||
</div>
|
||||
)}
|
||||
</dl>
|
||||
|
||||
{/* Inline progress bar (visible when execution has progress artifacts) */}
|
||||
|
||||
Reference in New Issue
Block a user