Skip to content

Commit

Permalink
use LegacyWorkflowInvocationElementView since we need job ids
Browse files Browse the repository at this point in the history
for the invocation graph view
  • Loading branch information
ahmedhamidawan committed Nov 7, 2024
1 parent a0661a3 commit 78f653c
Show file tree
Hide file tree
Showing 11 changed files with 73 additions and 40 deletions.
2 changes: 2 additions & 0 deletions client/src/api/invocations.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { type components } from "./schema";

export type WorkflowInvocationElementView = components["schemas"]["WorkflowInvocationElementView"];
export type LegacyWorkflowInvocationElementView = components["schemas"]["LegacyWorkflowInvocationElementView"];
export type WorkflowInvocationCollectionView = components["schemas"]["WorkflowInvocationCollectionView"];
export type WorkflowInvocationStepStatesView = components["schemas"]["WorkflowInvocationStepStatesView"];
export type InvocationJobsSummary = components["schemas"]["InvocationJobsResponse"];
export type InvocationStep = components["schemas"]["InvocationStep"];
export type LegacyInvocationStep = components["schemas"]["LegacyInvocationStep"];
export type InvocationMessage = components["schemas"]["InvocationMessageResponseUnion"];

export type StepJobSummary =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { BAlert, BButton, BCard, BCardBody, BCardHeader } from "bootstrap-vue";
import { storeToRefs } from "pinia";
import { computed, onUnmounted, ref, watch } from "vue";
import type { WorkflowInvocationElementView } from "@/api/invocations";
import type { LegacyWorkflowInvocationElementView } from "@/api/invocations";
import { JobProvider } from "@/components/providers";
import { useDatatypesMapper } from "@/composables/datatypesMapper";
import { useInvocationGraph } from "@/composables/useInvocationGraph";
Expand All @@ -35,7 +35,7 @@ library.add(faArrowDown, faChevronDown, faChevronUp, faSignInAlt, faSitemap, faT
interface Props {
/** The invocation to display */
invocation: WorkflowInvocationElementView;
invocation: LegacyWorkflowInvocationElementView;
/** The workflow which was run */
workflow: Workflow;
/** Whether the invocation is terminal */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { faChevronDown, faChevronUp, faSignInAlt } from "@fortawesome/free-solid
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
import { computed, nextTick, ref, watch } from "vue";
import type { WorkflowInvocationElementView } from "@/api/invocations";
import type { LegacyWorkflowInvocationElementView } from "@/api/invocations";
import { isWorkflowInput } from "@/components/Workflow/constants";
import type { GraphStep } from "@/composables/useInvocationGraph";
import type { Workflow } from "@/stores/workflowStore";
Expand All @@ -19,7 +19,7 @@ interface Props {
/** The store id for the invocation graph */
storeId: string;
/** The invocation to display */
invocation: WorkflowInvocationElementView;
invocation: LegacyWorkflowInvocationElementView;
/** The workflow which was run */
workflow: Workflow;
/** Whether the invocation graph is hidden */
Expand Down
10 changes: 3 additions & 7 deletions client/src/components/Workflow/InvocationsListState.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
<script setup lang="ts">
import { computed, onBeforeUnmount, onMounted, toRef } from "vue";
import { onBeforeUnmount, onMounted, toRef } from "vue";
import type { WorkflowInvocationElementView } from "@/api/invocations";
import { useInvocationState } from "@/components/WorkflowInvocationState/usesInvocationState";
import HelpText from "@/components/Help/HelpText.vue";
Expand All @@ -17,17 +16,14 @@ interface Props {
const props = defineProps<Props>();
const {
invocation: invocationFromState,
invocation,
invocationState,
invocationSchedulingTerminal,
invocationAndJobTerminal,
jobStatesSummary,
monitorState,
clearStateMonitor,
} = useInvocationState(toRef(props, "invocationId"), true);
// TODO: This is a workaround to type invocation; I would've expected it to already be typed
const invocation = computed(() => invocationFromState.value as WorkflowInvocationElementView | undefined);
} = useInvocationState(toRef(props, "invocationId"), "step_states");
onMounted(monitorState);
onBeforeUnmount(clearStateMonitor);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
<script setup lang="ts">
import { computed } from "vue";
import { type InvocationStep, type WorkflowInvocationElementView } from "@/api/invocations";
import {
type LegacyWorkflowInvocationElementView,
type WorkflowInvocationElementView,
type WorkflowInvocationStepStatesView,
} from "@/api/invocations";
import ProgressBar from "@/components/ProgressBar.vue";
interface Props {
invocation?: WorkflowInvocationElementView;
invocation?: WorkflowInvocationElementView | WorkflowInvocationStepStatesView | LegacyWorkflowInvocationElementView;
invocationState: string;
invocationSchedulingTerminal: boolean;
}
Expand All @@ -24,12 +28,12 @@ const stepStates = computed<StepStateType>(() => {
if (!props.invocation) {
return {};
}
const steps: InvocationStep[] = props.invocation?.steps || [];
const steps = props.invocation?.steps || [];
for (const step of steps) {
if (!step) {
const stepState = step.state;
if (!stepState) {
continue;
}
const stepState: string = step.state;
if (!stepStates[stepState]) {
stepStates[stepState] = 1;
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { computed, ref } from "vue";
import { RouterLink } from "vue-router";
import { isRegisteredUser } from "@/api";
import type { WorkflowInvocationElementView } from "@/api/invocations";
import type { WorkflowInvocation } from "@/api/invocations";
import { useWorkflowInstance } from "@/composables/useWorkflowInstance";
import { useUserStore } from "@/stores/userStore";
import type { Workflow } from "@/stores/workflowStore";
Expand All @@ -25,7 +25,7 @@ import WorkflowInvocationsCount from "../Workflow/WorkflowInvocationsCount.vue";
import WorkflowRunButton from "../Workflow/WorkflowRunButton.vue";
interface Props {
invocation: WorkflowInvocationElementView;
invocation: WorkflowInvocation;
fromPanel?: boolean;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { BAlert, BButton } from "bootstrap-vue";
import { computed } from "vue";
import { type InvocationJobsSummary, type WorkflowInvocationElementView } from "@/api/invocations";
import { type InvocationJobsSummary, type LegacyWorkflowInvocationElementView } from "@/api/invocations";
import { useWorkflowInstance } from "@/composables/useWorkflowInstance";
import { getRootFromIndexLink } from "@/onload";
import { withPrefix } from "@/utils/redirect";
Expand All @@ -22,7 +22,7 @@ function getUrl(path: string): string {
}
interface Props {
invocation: WorkflowInvocationElementView;
invocation: LegacyWorkflowInvocationElementView;
invocationAndJobTerminal: boolean;
invocationSchedulingTerminal: boolean;
isFullPage?: boolean;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { BAlert, BTab, BTabs } from "bootstrap-vue";
import { computed, onBeforeUnmount, onMounted, onUnmounted, ref, toRef, watch } from "vue";
import { type InvocationJobsSummary, type WorkflowInvocationElementView } from "@/api/invocations";
import { type InvocationJobsSummary } from "@/api/invocations";
import { useAnimationFrameResizeObserver } from "@/composables/sensors/animationFrameResizeObserver";
import { useInvocationStore } from "@/stores/invocationStore";
import { useWorkflowStore } from "@/stores/workflowStore";
Expand Down Expand Up @@ -120,16 +120,13 @@ async function pollJobStatesUntilTerminal() {
}
const {
invocation: invocationFromState,
invocation,
invocationSchedulingTerminal,
invocationAndJobTerminal,
jobStatesSummary,
monitorState,
clearStateMonitor,
} = useInvocationState(toRef(props, "invocationId"));
// TODO: This is a workaround to type invocation; I would've expected it to already be typed
const invocation = computed(() => invocationFromState.value as WorkflowInvocationElementView | undefined);
} = useInvocationState(toRef(props, "invocationId"), "legacy");
onMounted(monitorState);
onBeforeUnmount(clearStateMonitor);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,31 @@
import { computed, type Ref } from "vue";

import { type InvocationJobsSummary } from "@/api/invocations";
import {
type InvocationJobsSummary,
type LegacyWorkflowInvocationElementView,
type WorkflowInvocationElementView,
type WorkflowInvocationStepStatesView,
} from "@/api/invocations";
import { useInvocationStore } from "@/stores/invocationStore";

import { isTerminal, jobCount } from "./util";

type OptionalInterval = ReturnType<typeof setInterval> | null;

export function useInvocationState(invocationId: Ref<string>, fetchMinimal: boolean = false) {
export function useInvocationState(invocationId: Ref<string>, view: "element" | "step_states" | "legacy" = "element") {
const invocationStore = useInvocationStore();

const invocation = computed(() => {
if (fetchMinimal) {
return invocationStore.getInvocationWithStepStatesById(invocationId.value);
if (view === "step_states") {
return invocationStore.getInvocationWithStepStatesById(
invocationId.value
) as WorkflowInvocationStepStatesView;
} else if (view === "legacy") {
return invocationStore.getInvocationWithJobStepIdsById(
invocationId.value
) as LegacyWorkflowInvocationElementView;
} else {
return invocationStore.getInvocationById(invocationId.value);
return invocationStore.getInvocationById(invocationId.value) as WorkflowInvocationElementView;
}
});

Expand Down Expand Up @@ -51,8 +62,10 @@ export function useInvocationState(invocationId: Ref<string>, fetchMinimal: bool

async function pollStepStatesUntilTerminal() {
if (!invocation.value || !invocationSchedulingTerminal.value) {
if (fetchMinimal) {
if (view === "step_states") {
await invocationStore.fetchInvocationWithStepStatesForId({ id: invocationId.value });
} else if (view === "legacy") {
await invocationStore.fetchInvocationWithJobStepIdsForId({ id: invocationId.value });
} else {
await invocationStore.fetchInvocationForId({ id: invocationId.value });
}
Expand Down
20 changes: 13 additions & 7 deletions client/src/composables/useInvocationGraph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ import {
import { computed, type Ref, ref, set } from "vue";

import { GalaxyApi } from "@/api";
import { type InvocationStep, type StepJobSummary, type WorkflowInvocationElementView } from "@/api/invocations";
import {
type LegacyInvocationStep,
type LegacyWorkflowInvocationElementView,
type StepJobSummary,
} from "@/api/invocations";
import { isWorkflowInput } from "@/components/Workflow/constants";
import { fromSimple } from "@/components/Workflow/Editor/modules/model";
import { getWorkflowFull } from "@/components/Workflow/workflows.services";
Expand Down Expand Up @@ -67,7 +71,7 @@ const ALL_INSTANCES_STATES = ["deleted", "skipped", "new", "queued"];
* @param workflowId - The id of the workflow that was invoked
*/
export function useInvocationGraph(
invocation: Ref<WorkflowInvocationElementView>,
invocation: Ref<LegacyWorkflowInvocationElementView>,
workflowId: string | undefined,
workflowVersion: number | undefined
) {
Expand Down Expand Up @@ -169,7 +173,7 @@ export function useInvocationGraph(
invocationStepSummary = stepsJobsSummary.find((stepJobSummary: StepJobSummary) => {
if (stepJobSummary.model === "ImplicitCollectionJobs") {
return stepJobSummary.id === invocationStep.implicit_collection_jobs_id;
} else {
} else if (stepJobSummary.model === "Job") {
return stepJobSummary.id === invocationStep.job_id;
}
});
Expand All @@ -194,7 +198,7 @@ export function useInvocationGraph(
*/
function updateStep(
graphStep: GraphStep,
invocationStep: InvocationStep | undefined,
invocationStep: LegacyInvocationStep | undefined,
invocationStepSummary: StepJobSummary | undefined
) {
/** The new state for the graph step */
Expand Down Expand Up @@ -240,9 +244,11 @@ export function useInvocationGraph(

// If the state still hasn't been set, set it based on the populated state
if (!newState) {
if (populatedState === "scheduled" || populatedState === "ready") {
newState = "queued";
} else if (populatedState === "resubmitted") {
// These states are apparently not in the schema anymore
// if (populatedState === "scheduled" || populatedState === "ready") {
// newState = "queued";
// } else
if (populatedState === "resubmitted") {
newState = "new";
} else if (populatedState === "failed") {
newState = "error";
Expand Down
17 changes: 16 additions & 1 deletion client/src/stores/invocationStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,16 @@ export const useInvocationStore = defineStore("invocationStore", () => {
return data;
}

async function fetchInvocationDetailsJobStepIds(params: FetchParams): Promise<WorkflowInvocation> {
const { data, error } = await GalaxyApi().GET("/api/invocations/{invocation_id}", {
params: { path: { invocation_id: params.id }, query: { legacy_job_state: true } },
});
if (error) {
rethrowSimple(error);
}
return data;
}

async function fetchInvocationJobsSummary(params: FetchParams): Promise<InvocationJobsSummary> {
const { data, error } = await GalaxyApi().GET("/api/invocations/{invocation_id}/jobs_summary", {
params: { path: { invocation_id: params.id } },
Expand All @@ -43,7 +53,7 @@ export const useInvocationStore = defineStore("invocationStore", () => {

async function fetchInvocationStepStateDetails(params: FetchParams): Promise<WorkflowInvocationStepStatesView> {
const { data, error } = await GalaxyApi().GET("/api/invocations/{invocation_id}", {
params: { path: { invocation_id: params.id }, view: "step_states" },
params: { path: { invocation_id: params.id }, query: { view: "step_states" } },
});
if (error) {
rethrowSimple(error);
Expand All @@ -54,6 +64,9 @@ export const useInvocationStore = defineStore("invocationStore", () => {
const { getItemById: getInvocationById, fetchItemById: fetchInvocationForId } =
useKeyedCache<WorkflowInvocation>(fetchInvocationDetails);

const { getItemById: getInvocationWithJobStepIdsById, fetchItemById: fetchInvocationWithJobStepIdsForId } =
useKeyedCache<WorkflowInvocation>(fetchInvocationDetailsJobStepIds);

const { getItemById: getInvocationWithStepStatesById, fetchItemById: fetchInvocationWithStepStatesForId } =
useKeyedCache<WorkflowInvocation>(fetchInvocationStepStateDetails);

Expand All @@ -66,6 +79,8 @@ export const useInvocationStore = defineStore("invocationStore", () => {
return {
getInvocationById,
fetchInvocationForId,
getInvocationWithJobStepIdsById,
fetchInvocationWithJobStepIdsForId,
getInvocationJobsSummaryById,
fetchInvocationJobsSummaryForId,
getInvocationStepById,
Expand Down

0 comments on commit 78f653c

Please sign in to comment.