mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-10-24 02:04:04 +08:00
Migrate job metrics store and component to use pinia and composition api
This commit is contained in:
@@ -1,12 +1,10 @@
|
||||
import { mount, createLocalVue } from "@vue/test-utils";
|
||||
import flushPromises from "flush-promises";
|
||||
import JobMetrics from "./JobMetrics";
|
||||
import { createTestingPinia } from "@pinia/testing";
|
||||
import ec2 from "./ec2.json";
|
||||
import Vuex from "vuex";
|
||||
import createCache from "vuex-cache";
|
||||
import { jobMetricsStore } from "store/jobMetricsStore";
|
||||
|
||||
const JOB_ID = "moo";
|
||||
import flushPromises from "flush-promises";
|
||||
import { getLocalVue } from "tests/jest/helpers";
|
||||
import JobMetrics from "./JobMetrics";
|
||||
import { mount } from "@vue/test-utils";
|
||||
import { setActivePinia } from "pinia";
|
||||
|
||||
// Ignore all axios calls, data is mocked locally -- just say "OKAY!"
|
||||
jest.mock("axios", () => ({
|
||||
@@ -15,54 +13,57 @@ jest.mock("axios", () => ({
|
||||
},
|
||||
}));
|
||||
|
||||
const localVue = createLocalVue();
|
||||
localVue.use(Vuex);
|
||||
const testStore = new Vuex.Store({
|
||||
plugins: [createCache()],
|
||||
modules: {
|
||||
jobMetricsStore,
|
||||
},
|
||||
});
|
||||
const localVue = getLocalVue();
|
||||
|
||||
describe("JobMetrics/JobMetrics.vue", () => {
|
||||
it("should not render a div if no plugins found in store", async () => {
|
||||
const propsData = {
|
||||
jobId: JOB_ID,
|
||||
};
|
||||
const wrapper = mount(JobMetrics, {
|
||||
store: testStore,
|
||||
propsData,
|
||||
pinia: createTestingPinia(),
|
||||
propsData: {
|
||||
jobId: "9000",
|
||||
},
|
||||
localVue,
|
||||
});
|
||||
|
||||
await wrapper.vm.$nextTick();
|
||||
expect(wrapper.find("div").exists()).toBe(false);
|
||||
});
|
||||
|
||||
it("should group plugins by type", async () => {
|
||||
const propsData = {
|
||||
jobId: JOB_ID,
|
||||
};
|
||||
const metricsResponse = [
|
||||
const JOB_ID = "9000";
|
||||
const mockMetricsResponse = [
|
||||
{ plugin: "core", title: "runtime", value: 145 },
|
||||
{ plugin: "core", title: "memory", value: 146 },
|
||||
{ plugin: "extended", title: "awesomeness", value: 42 },
|
||||
];
|
||||
const wrapper = mount(JobMetrics, {
|
||||
store: testStore,
|
||||
propsData,
|
||||
localVue,
|
||||
computed: {
|
||||
jobMetrics() {
|
||||
return metricsResponse;
|
||||
|
||||
const pinia = createTestingPinia({
|
||||
initialState: {
|
||||
jobMetricsStore: {
|
||||
jobMetricsByJobId: {
|
||||
[`${JOB_ID}`]: mockMetricsResponse,
|
||||
},
|
||||
jobMetricsByHdaId: {},
|
||||
jobMetricsByLddaId: {},
|
||||
},
|
||||
},
|
||||
});
|
||||
setActivePinia(pinia);
|
||||
|
||||
const wrapper = mount(JobMetrics, {
|
||||
localVue,
|
||||
pinia,
|
||||
propsData: {
|
||||
jobId: JOB_ID,
|
||||
},
|
||||
});
|
||||
|
||||
// Wait for axios and rendering.
|
||||
await flushPromises();
|
||||
expect(wrapper.vm.jobMetrics.length).toBe(3);
|
||||
expect(wrapper.vm.jobId).toBe(JOB_ID);
|
||||
expect(wrapper.vm.metricsByPlugins.core.runtime).toBe(145);
|
||||
expect(wrapper.vm.orderedPlugins.length).toBe(2);
|
||||
expect(wrapper.vm.jobMetricsGroupedByPluginType.core.runtime).toBe(145);
|
||||
expect(wrapper.vm.pluginsSortedByPluginType.length).toBe(2);
|
||||
|
||||
// Three metrics, begin metrics for two plugins
|
||||
const metricsTables = wrapper.findAll(".metrics_plugin");
|
||||
expect(metricsTables.length).toBe(2);
|
||||
@@ -72,45 +73,53 @@ describe("JobMetrics/JobMetrics.vue", () => {
|
||||
expect(metricsTables.at(1).findAll("tr").length).toBe(1);
|
||||
});
|
||||
|
||||
it("should render correct AWS Estimates", async () => {
|
||||
it("renders correct AWS estimates", async () => {
|
||||
const deriveRenderedAwsEstimate = async (cores, seconds, memory) => {
|
||||
const JOB_ID = Math.random().toString(36).substring(2);
|
||||
const propsData = {
|
||||
jobId: JOB_ID,
|
||||
aws_estimate: true,
|
||||
};
|
||||
const metricsResponse = [
|
||||
const mockMetricsResponse = [
|
||||
{ plugin: "core", name: "galaxy_slots", raw_value: cores },
|
||||
{ plugin: "core", name: "runtime_seconds", raw_value: seconds },
|
||||
{ plugin: "core", name: "galaxy_memory_mb", raw_value: memory },
|
||||
];
|
||||
const wrapper = mount(JobMetrics, {
|
||||
store: testStore,
|
||||
propsData,
|
||||
localVue,
|
||||
computed: {
|
||||
jobMetrics() {
|
||||
return metricsResponse;
|
||||
|
||||
const pinia = createTestingPinia({
|
||||
initialState: {
|
||||
jobMetricsStore: {
|
||||
jobMetricsByJobId: {
|
||||
[`${JOB_ID}`]: mockMetricsResponse,
|
||||
},
|
||||
jobMetricsByHdaId: {},
|
||||
jobMetricsByLddaId: {},
|
||||
},
|
||||
},
|
||||
});
|
||||
setActivePinia(pinia);
|
||||
|
||||
const wrapper = mount(JobMetrics, {
|
||||
localVue,
|
||||
pinia,
|
||||
propsData: {
|
||||
jobId: JOB_ID,
|
||||
aws_estimate: true,
|
||||
},
|
||||
});
|
||||
|
||||
// Wait for axios and rendering.
|
||||
await flushPromises();
|
||||
|
||||
const estimates = {};
|
||||
|
||||
if (!wrapper.find("#aws-estimate").exists()) {
|
||||
return false;
|
||||
if (wrapper.find("#aws-estimate").exists()) {
|
||||
return {
|
||||
cost: wrapper.find("#aws-estimate b").text(),
|
||||
vcpus: wrapper.find("#aws_vcpus").text(),
|
||||
cpu: wrapper.find("#aws_cpu").text(),
|
||||
mem: wrapper.find("#aws_mem").text(),
|
||||
name: wrapper.find("#aws_name").text(),
|
||||
};
|
||||
}
|
||||
|
||||
estimates.cost = wrapper.find("#aws-estimate b").text();
|
||||
estimates.vcpus = wrapper.find("#aws_vcpus").text();
|
||||
estimates.cpu = wrapper.find("#aws_cpu").text();
|
||||
estimates.mem = wrapper.find("#aws_mem").text();
|
||||
estimates.name = wrapper.find("#aws_name").text();
|
||||
|
||||
return estimates;
|
||||
return {};
|
||||
};
|
||||
|
||||
const assertAwsInstance = (estimates) => {
|
||||
const instance = ec2.find((instance) => estimates.name === instance.name);
|
||||
expect(estimates.mem).toBe(instance.mem.toString());
|
||||
@@ -119,7 +128,6 @@ describe("JobMetrics/JobMetrics.vue", () => {
|
||||
};
|
||||
|
||||
const estimates_small = await deriveRenderedAwsEstimate("1.0000000", "9.0000000", "2048.0000000");
|
||||
|
||||
expect(estimates_small.name).toBe("t2.small");
|
||||
expect(estimates_small.cost).toBe("0.00 USD");
|
||||
assertAwsInstance(estimates_small);
|
||||
@@ -134,6 +142,6 @@ describe("JobMetrics/JobMetrics.vue", () => {
|
||||
"18000.0000000",
|
||||
"99999.0000000"
|
||||
);
|
||||
expect(estimates_not_available).toBe(false);
|
||||
expect(estimates_not_available).toEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,11 +1,127 @@
|
||||
<script setup lang="ts">
|
||||
import ec2 from "./ec2.json";
|
||||
import { useJobMetricsStore } from "@/stores/jobMetricsStore";
|
||||
import { computed, onMounted } from "vue";
|
||||
|
||||
const props = defineProps({
|
||||
jobId: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
datasetId: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
// eslint-disable-next-line vue/prop-name-casing
|
||||
aws_estimate: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
datasetType: {
|
||||
type: String,
|
||||
default: "hda",
|
||||
},
|
||||
includeTitle: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
});
|
||||
|
||||
const jobMetricsStore = useJobMetricsStore();
|
||||
|
||||
onMounted(async () => {
|
||||
if (props.jobId) {
|
||||
await jobMetricsStore.fetchJobMetricsForJobId(props.jobId);
|
||||
} else {
|
||||
await jobMetricsStore.fetchJobMetricsForDatasetId(props.datasetId, props.datasetType);
|
||||
}
|
||||
});
|
||||
|
||||
const jobMetrics = computed(() => {
|
||||
if (props.jobId) {
|
||||
return jobMetricsStore.getJobMetricsByJobId(props.jobId);
|
||||
} else {
|
||||
return jobMetricsStore.getJobMetricsByDatasetId(props.datasetId, props.datasetType);
|
||||
}
|
||||
});
|
||||
|
||||
const jobMetricsGroupedByPluginType = computed(() => {
|
||||
const pluginGroups: Record<string, any> = {};
|
||||
|
||||
for (const metric of jobMetrics.value) {
|
||||
// new group found
|
||||
if (!(metric.plugin in pluginGroups)) {
|
||||
pluginGroups[metric.plugin] = {};
|
||||
}
|
||||
|
||||
const group = pluginGroups[metric.plugin];
|
||||
group[metric.title] = metric.value;
|
||||
}
|
||||
|
||||
return pluginGroups;
|
||||
});
|
||||
|
||||
const pluginsSortedByPluginType = computed(() => {
|
||||
return Object.keys(jobMetricsGroupedByPluginType.value).sort();
|
||||
});
|
||||
|
||||
const computedAwsEstimate = computed(() => {
|
||||
if (!props.aws_estimate) {
|
||||
return;
|
||||
}
|
||||
|
||||
const aws: Record<string, any> = {};
|
||||
|
||||
for (const metric of jobMetrics.value) {
|
||||
switch (metric.name) {
|
||||
case "galaxy_memory_mb":
|
||||
aws.memory = parseInt(metric.raw_value);
|
||||
break;
|
||||
case "galaxy_slots":
|
||||
aws.vcpus = parseInt(metric.raw_value);
|
||||
break;
|
||||
case "runtime_seconds":
|
||||
aws.seconds = parseInt(metric.raw_value);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
if (aws.memory) {
|
||||
aws.memory /= 1024;
|
||||
} else {
|
||||
// if memory was not specified, assign the smallest amount (we judge based on CPU-count only)
|
||||
aws.memory = 0.5;
|
||||
}
|
||||
|
||||
// ec2 is already pre-sorted
|
||||
aws.instance = ec2.find((ec) => {
|
||||
return ec.mem >= aws.memory && ec.vcpus >= aws.vcpus;
|
||||
});
|
||||
|
||||
if (!aws.instance) {
|
||||
return;
|
||||
}
|
||||
|
||||
aws.price = ((aws.seconds * aws.instance.price) / 3600).toFixed(2);
|
||||
|
||||
return aws;
|
||||
});
|
||||
|
||||
defineExpose({ jobMetricsGroupedByPluginType, pluginsSortedByPluginType });
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="orderedPlugins.length > 0">
|
||||
<div v-if="pluginsSortedByPluginType.length > 0">
|
||||
<h2 v-if="includeTitle" class="h-md">Job Metrics</h2>
|
||||
<div v-for="plugin in orderedPlugins" :key="plugin" class="metrics_plugin">
|
||||
<h3 class="metrics_plugin_title m-sm">{{ plugin }}</h3>
|
||||
<div v-for="pluginType in pluginsSortedByPluginType" :key="pluginType" class="metrics_plugin">
|
||||
<h3 class="metrics_plugin_title m-sm">{{ pluginType }}</h3>
|
||||
|
||||
<table class="tabletip info_data_table">
|
||||
<tbody>
|
||||
<tr v-for="(metricValue, metricTitle) in metricsByPlugins[plugin]" :key="metricTitle">
|
||||
<tr
|
||||
v-for="(metricValue, metricTitle) in jobMetricsGroupedByPluginType[pluginType]"
|
||||
:key="metricTitle">
|
||||
<td>{{ metricTitle }}</td>
|
||||
<td>{{ metricValue }}</td>
|
||||
</tr>
|
||||
@@ -16,122 +132,25 @@
|
||||
<div v-if="aws_estimate && computedAwsEstimate" id="aws-estimate">
|
||||
<div class="aws">
|
||||
<h3>AWS estimate</h3>
|
||||
|
||||
<b>{{ computedAwsEstimate.price }} USD</b><br />
|
||||
This job requested {{ computedAwsEstimate.vcpus }} cores and {{ computedAwsEstimate.memory }} Gb. Given
|
||||
this, the smallest EC2 machine we could find is
|
||||
<span id="aws_name">{{ computedAwsEstimate.instance.name }}</span> (<span id="aws_mem">{{
|
||||
This job requested {{ computedAwsEstimate.vcpus }} core{{
|
||||
computedAwsEstimate.vcpus > 1 ? "s" : ""
|
||||
}}
|
||||
and {{ computedAwsEstimate.memory }} Gb. Given this information, the smallest EC2 machine we could find
|
||||
is <span id="aws_name">{{ computedAwsEstimate.instance.name }}</span> (<span id="aws_mem">{{
|
||||
computedAwsEstimate.instance.mem
|
||||
}}</span>
|
||||
GB / <span id="aws_vcpus">{{ computedAwsEstimate.instance.vcpus }}</span> vCPUs /
|
||||
<span id="aws_cpu">{{ computedAwsEstimate.instance.cpu }}</span
|
||||
>). That instance is priced at {{ computedAwsEstimate.instance.price }} USD/hour.<br />
|
||||
Please note, that those numbers are only estimates, all jobs are always free of charge for all users.
|
||||
>). This instance is priced at {{ computedAwsEstimate.instance.price }} USD/hour.<br />
|
||||
*Please note, that these numbers are only estimates, all jobs are always free of charge for all
|
||||
users.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapCacheActions } from "vuex-cache";
|
||||
import { mapGetters } from "vuex";
|
||||
import ec2 from "./ec2.json";
|
||||
|
||||
export default {
|
||||
props: {
|
||||
jobId: {
|
||||
type: String,
|
||||
},
|
||||
datasetId: {
|
||||
type: String,
|
||||
},
|
||||
aws_estimate: {
|
||||
type: Boolean,
|
||||
},
|
||||
datasetType: {
|
||||
type: String,
|
||||
default: "hda",
|
||||
},
|
||||
includeTitle: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(["getJobMetricsByDatasetId", "getJobMetricsByJobId"]),
|
||||
computedAwsEstimate: function () {
|
||||
if (!this.aws_estimate) {
|
||||
return;
|
||||
}
|
||||
|
||||
const aws = {};
|
||||
this.jobMetrics.forEach((metric) => {
|
||||
switch (metric.name) {
|
||||
case "galaxy_memory_mb":
|
||||
aws.memory = parseInt(metric.raw_value);
|
||||
break;
|
||||
case "galaxy_slots":
|
||||
aws.vcpus = parseInt(metric.raw_value);
|
||||
break;
|
||||
case "runtime_seconds":
|
||||
aws.seconds = parseInt(metric.raw_value);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
});
|
||||
|
||||
if (aws.memory) {
|
||||
aws.memory /= 1024;
|
||||
}
|
||||
// if memory was not specified, assign the smallest amount (we judge based on CPU-count only)
|
||||
else {
|
||||
aws.memory = 0.5;
|
||||
}
|
||||
|
||||
// ec2 is already pre-sorted
|
||||
aws.instance = ec2.find((ec) => {
|
||||
return ec.mem >= aws.memory && ec.vcpus >= aws.vcpus;
|
||||
});
|
||||
if (aws.instance === undefined) {
|
||||
return;
|
||||
}
|
||||
aws.price = ((aws.seconds * aws.instance.price) / 3600).toFixed(2);
|
||||
return aws;
|
||||
},
|
||||
jobMetrics: function () {
|
||||
if (this.jobId) {
|
||||
return this.getJobMetricsByJobId(this.jobId);
|
||||
} else {
|
||||
return this.getJobMetricsByDatasetId(this.datasetId, this.datasetType);
|
||||
}
|
||||
},
|
||||
metricsByPlugins: function () {
|
||||
const metricsByPlugins = {};
|
||||
const metrics = this.jobMetrics;
|
||||
metrics.forEach((metric) => {
|
||||
if (!(metric.plugin in metricsByPlugins)) {
|
||||
metricsByPlugins[metric.plugin] = {};
|
||||
}
|
||||
const metricsForPlugin = metricsByPlugins[metric.plugin];
|
||||
metricsForPlugin[metric.title] = metric.value;
|
||||
});
|
||||
return metricsByPlugins;
|
||||
},
|
||||
orderedPlugins: function () {
|
||||
return Object.keys(this.metricsByPlugins).sort();
|
||||
},
|
||||
},
|
||||
created: function () {
|
||||
if (this.jobId) {
|
||||
this.fetchJobMetricsForJobId(this.jobId);
|
||||
} else {
|
||||
this.fetchJobMetricsForDatasetId({ datasetId: this.datasetId, datasetType: this.datasetType });
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapCacheActions(["fetchJobMetricsForDatasetId", "fetchJobMetricsForJobId"]),
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style scoped>
|
||||
.aws {
|
||||
padding-top: 0.6rem;
|
||||
|
||||
@@ -12,7 +12,6 @@ import config from "config";
|
||||
|
||||
import { gridSearchStore } from "./gridSearchStore";
|
||||
import { tagStore } from "./tagStore";
|
||||
import { jobMetricsStore } from "./jobMetricsStore";
|
||||
import { jobDestinationParametersStore } from "./jobDestinationParametersStore";
|
||||
import { invocationStore } from "./invocationStore";
|
||||
import { collectionElementsStore, datasetStore } from "./historyStore";
|
||||
@@ -59,7 +58,6 @@ export function createStore() {
|
||||
datasetExtFiles: datasetExtFilesStore,
|
||||
datasetPathDestination: datasetPathDestinationStore,
|
||||
invocations: invocationStore,
|
||||
jobMetrics: jobMetricsStore,
|
||||
gridSearch: gridSearchStore,
|
||||
panels: panelStore,
|
||||
tags: tagStore,
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
export const state = {
|
||||
jobMetricsByHdaId: {},
|
||||
jobMetricsByLddaId: {},
|
||||
jobMetricsByJobId: {},
|
||||
};
|
||||
|
||||
import Vue from "vue";
|
||||
import { getAppRoot } from "onload/loadConfig";
|
||||
import axios from "axios";
|
||||
|
||||
const getters = {
|
||||
getJobMetricsByDatasetId:
|
||||
(state) =>
|
||||
(datasetId, datasetType = "hda") => {
|
||||
const jobMetricsObject = datasetType == "hda" ? state.jobMetricsByHdaId : state.jobMetricsByLddaId;
|
||||
return jobMetricsObject[datasetId] || [];
|
||||
},
|
||||
getJobMetricsByJobId: (state) => (jobId) => {
|
||||
return state.jobMetricsByJobId[jobId] || [];
|
||||
},
|
||||
};
|
||||
|
||||
const actions = {
|
||||
fetchJobMetricsForDatasetId: async ({ commit }, { datasetId, datasetType }) => {
|
||||
const { data } = await axios.get(`${getAppRoot()}api/datasets/${datasetId}/metrics?hda_ldda=${datasetType}`);
|
||||
commit("saveJobMetricsForDatasetId", { datasetId, datasetType, jobMetrics: data });
|
||||
},
|
||||
fetchJobMetricsForJobId: async ({ commit }, jobId) => {
|
||||
const { data } = await axios.get(`${getAppRoot()}api/jobs/${jobId}/metrics`);
|
||||
commit("saveJobMetricsForJobId", { jobId, jobMetrics: data });
|
||||
},
|
||||
};
|
||||
|
||||
const mutations = {
|
||||
saveJobMetricsForDatasetId: (state, { datasetId, datasetType, jobMetrics }) => {
|
||||
const jobMetricsObject = datasetType == "hda" ? state.jobMetricsByHdaId : state.jobMetricsByLddaId;
|
||||
Vue.set(jobMetricsObject, datasetId, jobMetrics);
|
||||
},
|
||||
saveJobMetricsForJobId: (state, { jobId, jobMetrics }) => {
|
||||
Vue.set(state.jobMetricsByJobId, jobId, jobMetrics);
|
||||
},
|
||||
};
|
||||
|
||||
export const jobMetricsStore = {
|
||||
state,
|
||||
getters,
|
||||
actions,
|
||||
mutations,
|
||||
};
|
||||
@@ -1,19 +0,0 @@
|
||||
import { jobMetricsStore } from "./jobMetricsStore";
|
||||
|
||||
describe("store/jobMetricsStore.js", () => {
|
||||
test("getter should return empty list for unfetched job IDs", () => {
|
||||
const state = {
|
||||
jobMetricsByJobId: {},
|
||||
};
|
||||
const metrics = jobMetricsStore.getters.getJobMetricsByJobId(state)("123");
|
||||
expect(metrics.length == 0).toBeTruthy();
|
||||
});
|
||||
|
||||
test("should simply return fetched metrics list for job ID", () => {
|
||||
const state = {
|
||||
jobMetricsByJobId: { 123: [{ plugin: "core", value: 123 }] },
|
||||
};
|
||||
const metrics = jobMetricsStore.getters.getJobMetricsByJobId(state)("123");
|
||||
expect(metrics.length == 1).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,69 @@
|
||||
import { createPinia, setActivePinia } from "pinia";
|
||||
import { useJobMetricsStore } from "./jobMetricsStore";
|
||||
|
||||
describe("stores/jobMetricsStore", () => {
|
||||
const testPlugin = { plugin: "core", value: "123", title: "foo", name: "bar", raw_value: "raw-chicken" };
|
||||
|
||||
beforeEach(() => {
|
||||
setActivePinia(createPinia());
|
||||
});
|
||||
|
||||
it("returns an empty list for unfetched job and dataset IDs.", () => {
|
||||
const jobMetricsStore = useJobMetricsStore();
|
||||
|
||||
jobMetricsStore.$state = {
|
||||
jobMetricsByJobId: {},
|
||||
jobMetricsByHdaId: {},
|
||||
jobMetricsByLddaId: {},
|
||||
};
|
||||
|
||||
expect(jobMetricsStore.getJobMetricsByJobId("123").length).toBe(0);
|
||||
expect(jobMetricsStore.getJobMetricsByDatasetId("123").length).toBe(0);
|
||||
expect(jobMetricsStore.getJobMetricsByDatasetId("123", "not-hda").length).toBe(0);
|
||||
});
|
||||
|
||||
it("returns metrics for job ID.", () => {
|
||||
const jobMetricsStore = useJobMetricsStore();
|
||||
|
||||
jobMetricsStore.$state = {
|
||||
jobMetricsByJobId: { 123: [testPlugin] },
|
||||
jobMetricsByHdaId: {},
|
||||
jobMetricsByLddaId: {},
|
||||
};
|
||||
|
||||
const metrics = jobMetricsStore.getJobMetricsByJobId("123");
|
||||
|
||||
expect(metrics.length).toBe(1);
|
||||
expect(metrics[0]).toEqual(testPlugin);
|
||||
});
|
||||
|
||||
it("returns metrics by hda ID for dataset ID by default.", () => {
|
||||
const jobMetricsStore = useJobMetricsStore();
|
||||
|
||||
jobMetricsStore.$state = {
|
||||
jobMetricsByJobId: {},
|
||||
jobMetricsByHdaId: { 123: [testPlugin] },
|
||||
jobMetricsByLddaId: {},
|
||||
};
|
||||
|
||||
const metrics = jobMetricsStore.getJobMetricsByDatasetId("123");
|
||||
|
||||
expect(metrics.length).toBe(1);
|
||||
expect(metrics[0]).toEqual(testPlugin);
|
||||
});
|
||||
|
||||
it("returns metrics by Ldda ID for dataset ID when dataset type is not hda.", () => {
|
||||
const jobMetricsStore = useJobMetricsStore();
|
||||
|
||||
jobMetricsStore.$state = {
|
||||
jobMetricsByJobId: {},
|
||||
jobMetricsByHdaId: {},
|
||||
jobMetricsByLddaId: { 123: [testPlugin] },
|
||||
};
|
||||
|
||||
const metrics = jobMetricsStore.getJobMetricsByDatasetId("123", "not-hda");
|
||||
|
||||
expect(metrics.length).toBe(1);
|
||||
expect(metrics[0]).toEqual(testPlugin);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,65 @@
|
||||
import axios from "axios";
|
||||
import { defineStore } from "pinia";
|
||||
import { prependPath } from "@/utils/redirect";
|
||||
import Vue, { computed, ref } from "vue";
|
||||
|
||||
interface JobMertic {
|
||||
title: string;
|
||||
value: string;
|
||||
plugin: string;
|
||||
name: string;
|
||||
raw_value: string;
|
||||
}
|
||||
|
||||
export const useJobMetricsStore = defineStore("jobMetricsStore", () => {
|
||||
const jobMetricsByHdaId = ref<Record<string, JobMertic[]>>({});
|
||||
const jobMetricsByLddaId = ref<Record<string, JobMertic[]>>({});
|
||||
const jobMetricsByJobId = ref<Record<string, JobMertic[]>>({});
|
||||
|
||||
const getJobMetricsByDatasetId = computed(() => {
|
||||
return (datasetId: string, datasetType = "hda") => {
|
||||
const jobMetricsObject = datasetType == "hda" ? jobMetricsByHdaId : jobMetricsByLddaId;
|
||||
return jobMetricsObject.value[datasetId] || ([] as JobMertic[]);
|
||||
};
|
||||
});
|
||||
|
||||
const getJobMetricsByJobId = computed(() => {
|
||||
return (jobId: string) => {
|
||||
return jobMetricsByJobId.value[jobId] || ([] as JobMertic[]);
|
||||
};
|
||||
});
|
||||
|
||||
async function fetchJobMetricsForDatasetId(datasetId: string, datasetType = "hda") {
|
||||
if (jobMetricsByHdaId.value[datasetId] || jobMetricsByLddaId.value[datasetId]) {
|
||||
return;
|
||||
}
|
||||
|
||||
const jobMetrics = (await axios.get(prependPath(`api/datasets/${datasetId}/metrics?hda_ldda=${datasetType}`)))
|
||||
.data as JobMertic[];
|
||||
const jobMetricsObject = datasetType == "hda" ? jobMetricsByHdaId : jobMetricsByLddaId;
|
||||
|
||||
Vue.set(jobMetricsObject.value, datasetId, jobMetrics);
|
||||
}
|
||||
|
||||
async function fetchJobMetricsForJobId(jobId: string) {
|
||||
if (jobMetricsByJobId.value[jobId]) {
|
||||
return;
|
||||
}
|
||||
|
||||
const jobMetrics = (await axios.get(prependPath(`api/jobs/${jobId}/metrics`))).data as JobMertic[];
|
||||
|
||||
Vue.set(jobMetricsByJobId.value, jobId, jobMetrics);
|
||||
}
|
||||
|
||||
return {
|
||||
jobMetricsByHdaId,
|
||||
jobMetricsByLddaId,
|
||||
jobMetricsByJobId,
|
||||
|
||||
getJobMetricsByDatasetId,
|
||||
getJobMetricsByJobId,
|
||||
|
||||
fetchJobMetricsForJobId,
|
||||
fetchJobMetricsForDatasetId,
|
||||
};
|
||||
});
|
||||
Reference in New Issue
Block a user