mirror of
https://github.com/ClusterCockpit/cc-backend
synced 2025-12-16 20:26:16 +01:00
add autorefresh, remove leftover query
This commit is contained in:
@@ -35,8 +35,7 @@
|
||||
import Pie, { colors } from "./generic/plots/Pie.svelte";
|
||||
import Stacked from "./generic/plots/Stacked.svelte";
|
||||
import DoubleMetric from "./generic/plots/DoubleMetricPlot.svelte";
|
||||
|
||||
// Todo: Refresher-Tick
|
||||
import Refresher from "./generic/helper/Refresher.svelte";
|
||||
|
||||
/* Svelte 5 Props */
|
||||
let {
|
||||
@@ -206,35 +205,6 @@
|
||||
requestPolicy: "network-only"
|
||||
}));
|
||||
|
||||
// Note: nodeMetrics are requested on configured $timestep resolution
|
||||
const nodeStatusQuery = $derived(queryStore({
|
||||
client: client,
|
||||
query: gql`
|
||||
query (
|
||||
$filter: [JobFilter!]!
|
||||
$selectedHistograms: [String!]
|
||||
$numDurationBins: String
|
||||
) {
|
||||
jobsStatistics(filter: $filter, metrics: $selectedHistograms, numDurationBins: $numDurationBins) {
|
||||
histNumCores {
|
||||
count
|
||||
value
|
||||
}
|
||||
histNumAccs {
|
||||
count
|
||||
value
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
variables: {
|
||||
filter: [{ state: ["running"] }, { cluster: { eq: presetCluster } }],
|
||||
selectedHistograms: [], // No Metrics requested for node hardware stats - Empty Array can be used for refresh
|
||||
numDurationBins: "1h", // Hardcode or selector?
|
||||
},
|
||||
requestPolicy: "network-only"
|
||||
}));
|
||||
|
||||
const clusterInfo = $derived.by(() => {
|
||||
if ($initq?.data?.clusters) {
|
||||
let rawInfos = {};
|
||||
@@ -368,28 +338,39 @@
|
||||
|
||||
<Card style="height: 98vh;">
|
||||
<CardBody class="align-content-center">
|
||||
{#if $statusQuery.fetching || $statesTimed.fetching || $nodeStatusQuery.fetching}
|
||||
<Row>
|
||||
<Col>
|
||||
<Refresher
|
||||
hideSelector
|
||||
initially={60}
|
||||
onRefresh={(interval) => {
|
||||
from = new Date(Date.now() - 5 * 60 * 1000);
|
||||
to = new Date(Date.now());
|
||||
clusterFrom = new Date(Date.now() - (8 * 60 * 60 * 1000))
|
||||
|
||||
if (interval) stackedFrom += Math.floor(interval / 1000);
|
||||
else stackedFrom += 1 // Workaround: TimeSelection not linked, just trigger new data on manual refresh
|
||||
}}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
{#if $statusQuery.fetching || $statesTimed.fetching}
|
||||
<Row class="justify-content-center">
|
||||
<Col xs="auto">
|
||||
<Spinner />
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
{:else if $statusQuery.error || $statesTimed.error || $nodeStatusQuery.error}
|
||||
{:else if $statusQuery.error || $statesTimed.error}
|
||||
<Row cols={{xs:1, md:2}}>
|
||||
{#if $statusQuery.error}
|
||||
<Col>
|
||||
<Card color="danger">Error Requesting StatusQuery: {$statusQuery.error.message}</Card>
|
||||
<Card color="danger"><CardBody>Error Requesting Status Data: {$statusQuery.error.message}</CardBody></Card>
|
||||
</Col>
|
||||
{/if}
|
||||
{#if $statesTimed.error}
|
||||
<Col>
|
||||
<Card color="danger">Error Requesting StatesTimed: {$statesTimed.error.message}</Card>
|
||||
</Col>
|
||||
{/if}
|
||||
{#if $nodeStatusQuery.error}
|
||||
<Col>
|
||||
<Card color="danger">Error Requesting NodeStatusQuery: {$nodeStatusQuery.error.message}</Card>
|
||||
<Card color="danger"><CardBody>Error Requesting Node Scheduler States: {$statesTimed.error.message}</CardBody></Card>
|
||||
</Col>
|
||||
{/if}
|
||||
</Row>
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
let {
|
||||
initially = null,
|
||||
presetClass = "",
|
||||
hideSelector = false,
|
||||
onRefresh
|
||||
} = $props();
|
||||
|
||||
@@ -36,25 +37,27 @@
|
||||
});
|
||||
</script>
|
||||
|
||||
<InputGroup class={presetClass}>
|
||||
<Input
|
||||
type="select"
|
||||
title="Periodic refresh interval"
|
||||
bind:value={refreshInterval}
|
||||
onchange={refreshIntervalChanged}
|
||||
>
|
||||
<option value={null}>No Interval</option>
|
||||
<option value={30 * 1000}>30 Seconds</option>
|
||||
<option value={60 * 1000}>60 Seconds</option>
|
||||
<option value={2 * 60 * 1000}>Two Minutes</option>
|
||||
<option value={5 * 60 * 1000}>5 Minutes</option>
|
||||
</Input>
|
||||
<Button
|
||||
outline
|
||||
onclick={() => onRefresh(refreshInterval)}
|
||||
disabled={refreshInterval != null}
|
||||
{#if !hideSelector}
|
||||
<InputGroup class={presetClass}>
|
||||
<Input
|
||||
type="select"
|
||||
title="Periodic refresh interval"
|
||||
bind:value={refreshInterval}
|
||||
onchange={refreshIntervalChanged}
|
||||
>
|
||||
<Icon name="arrow-clockwise" /> Refresh
|
||||
</Button>
|
||||
</InputGroup>
|
||||
<option value={null}>No Interval</option>
|
||||
<option value={30 * 1000}>30 Seconds</option>
|
||||
<option value={60 * 1000}>60 Seconds</option>
|
||||
<option value={2 * 60 * 1000}>Two Minutes</option>
|
||||
<option value={5 * 60 * 1000}>5 Minutes</option>
|
||||
</Input>
|
||||
<Button
|
||||
outline
|
||||
onclick={() => onRefresh(refreshInterval)}
|
||||
disabled={refreshInterval != null}
|
||||
>
|
||||
<Icon name="arrow-clockwise" /> Refresh
|
||||
</Button>
|
||||
</InputGroup>
|
||||
{/if}
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
import Pie, { colors } from "../generic/plots/Pie.svelte";
|
||||
import Stacked from "../generic/plots/Stacked.svelte";
|
||||
import DoubleMetric from "../generic/plots/DoubleMetricPlot.svelte";
|
||||
import Refresher from "../generic/helper/Refresher.svelte";
|
||||
|
||||
/* Svelte 5 Props */
|
||||
let {
|
||||
@@ -224,35 +225,6 @@
|
||||
requestPolicy: "network-only"
|
||||
}));
|
||||
|
||||
// Note: nodeMetrics are requested on configured $timestep resolution
|
||||
const nodeStatusQuery = $derived(queryStore({
|
||||
client: client,
|
||||
query: gql`
|
||||
query (
|
||||
$filter: [JobFilter!]!
|
||||
$selectedHistograms: [String!]
|
||||
$numDurationBins: String
|
||||
) {
|
||||
jobsStatistics(filter: $filter, metrics: $selectedHistograms, numDurationBins: $numDurationBins) {
|
||||
histNumCores {
|
||||
count
|
||||
value
|
||||
}
|
||||
histNumAccs {
|
||||
count
|
||||
value
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
variables: {
|
||||
filter: [{ state: ["running"] }, { cluster: { eq: presetCluster } }],
|
||||
selectedHistograms: [], // No Metrics requested for node hardware stats - Empty Array can be used for refresh
|
||||
numDurationBins: "1h", // Hardcode or selector?
|
||||
},
|
||||
requestPolicy: "network-only"
|
||||
}));
|
||||
|
||||
const clusterInfo = $derived.by(() => {
|
||||
if ($initq?.data?.clusters) {
|
||||
let rawInfos = {};
|
||||
@@ -385,33 +357,45 @@
|
||||
|
||||
<Card style="height: 88vh;">
|
||||
<CardBody class="align-content-center">
|
||||
{#if $statusQuery.fetching || $statesTimed.fetching || $topJobsQuery.fetching || $nodeStatusQuery.fetching}
|
||||
<Row>
|
||||
<Col>
|
||||
<Refresher
|
||||
hideSelector
|
||||
initially={60}
|
||||
onRefresh={(interval) => {
|
||||
from = new Date(Date.now() - 5 * 60 * 1000);
|
||||
to = new Date(Date.now());
|
||||
clusterFrom = new Date(Date.now() - (8 * 60 * 60 * 1000))
|
||||
pagingState = { page:1, itemsPerPage: 10 };
|
||||
|
||||
if (interval) stackedFrom += Math.floor(interval / 1000);
|
||||
else stackedFrom += 1 // Workaround: TimeSelection not linked, just trigger new data on manual refresh
|
||||
}}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
{#if $statusQuery.fetching || $statesTimed.fetching || $topJobsQuery.fetching}
|
||||
<Row class="justify-content-center">
|
||||
<Col xs="auto">
|
||||
<Spinner />
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
{:else if $statusQuery.error || $statesTimed.error || $topJobsQuery.error || $nodeStatusQuery.error}
|
||||
<Row cols={{xs:1, md:2}}>
|
||||
{:else if $statusQuery.error || $statesTimed.error || $topJobsQuery.error}
|
||||
<Row>
|
||||
{#if $statusQuery.error}
|
||||
<Col>
|
||||
<Card color="danger">Error Requesting StatusQuery: {$statusQuery.error.message}</Card>
|
||||
<Card color="danger"><CardBody>Error Requesting Status Data: {$statusQuery.error.message}</CardBody></Card>
|
||||
</Col>
|
||||
{/if}
|
||||
{#if $statesTimed.error}
|
||||
<Col>
|
||||
<Card color="danger">Error Requesting StatesTimed: {$statesTimed.error.message}</Card>
|
||||
<Card color="danger"><CardBody>Error Requesting Node Scheduler States: {$statesTimed.error.message}</CardBody></Card>
|
||||
</Col>
|
||||
{/if}
|
||||
{#if $topJobsQuery.error}
|
||||
<Col>
|
||||
<Card color="danger">Error Requesting TopJobsQuery: {$topJobsQuery.error.message}</Card>
|
||||
</Col>
|
||||
{/if}
|
||||
{#if $nodeStatusQuery.error}
|
||||
<Col>
|
||||
<Card color="danger">Error Requesting NodeStatusQuery: {$nodeStatusQuery.error.message}</Card>
|
||||
<Card color="danger"><CardBody>Error Requesting Jobs By Project: {$topJobsQuery.error.message}</CardBody></Card>
|
||||
</Col>
|
||||
{/if}
|
||||
</Row>
|
||||
|
||||
@@ -402,7 +402,7 @@
|
||||
to = new Date(Date.now());
|
||||
|
||||
if (interval) stackedFrom += Math.floor(interval / 1000);
|
||||
else stackedFrom += 1 // Workaround: TineSelection not linked, just trigger new data on manual refresh
|
||||
else stackedFrom += 1 // Workaround: TimeSelection not linked, just trigger new data on manual refresh
|
||||
}}
|
||||
/>
|
||||
</Col>
|
||||
|
||||
Reference in New Issue
Block a user