Start porting to new urql api

It compiles. Not tested
This commit is contained in:
Jan Eitzinger 2023-05-03 16:41:17 +02:00
parent ce8eb86569
commit f235b5e911
12 changed files with 224 additions and 142 deletions

View File

@ -1,7 +1,7 @@
<script> <script>
import { init } from './utils.js' import { init } from './utils.js'
import { getContext, onMount } from 'svelte' import { getContext, onMount } from 'svelte'
import { operationStore, query } from '@urql/svelte' import { queryStore, gql, getContextClient } from '@urql/svelte'
import { Row, Col, Spinner, Card, Table } from 'sveltestrap' import { Row, Col, Spinner, Card, Table } from 'sveltestrap'
import Filters from './filters/Filters.svelte' import Filters from './filters/Filters.svelte'
import PlotSelection from './PlotSelection.svelte' import PlotSelection from './PlotSelection.svelte'
@ -50,7 +50,9 @@
} }
}) })
const statsQuery = operationStore(` const statsQuery = queryStore({
client: getContextClient(),
query: gql`
query($filter: [JobFilter!]!) { query($filter: [JobFilter!]!) {
stats: jobsStatistics(filter: $filter) { stats: jobsStatistics(filter: $filter) {
totalJobs totalJobs
@ -63,33 +65,38 @@
topUsers: jobsCount(filter: $filter, groupBy: USER, weight: NODE_HOURS, limit: 5) { name, count } topUsers: jobsCount(filter: $filter, groupBy: USER, weight: NODE_HOURS, limit: 5) { name, count }
} }
`, { filter: [] }, { pause: true }) `,
variables: { filter: [] },
pause: true
})
const footprintsQuery = operationStore(` const footprintsQuery = queryStore({
client: getContextClient(),
query: gql`
query($filter: [JobFilter!]!, $metrics: [String!]!) { query($filter: [JobFilter!]!, $metrics: [String!]!) {
footprints: jobsFootprints(filter: $filter, metrics: $metrics) { footprints: jobsFootprints(filter: $filter, metrics: $metrics) {
nodehours, nodehours,
metrics { metric, data } metrics { metric, data }
} }
} }`,
`, { filter: [], metrics }, { pause: true }) variables: { filter: [], metrics },
pause: true
})
$: $footprintsQuery.variables = { ...$footprintsQuery.variables, metrics } $: $footprintsQuery.variables = { ...$footprintsQuery.variables, metrics }
const rooflineQuery = operationStore(` const rooflineQuery = queryStore({
client: getContextClient(),
query: gql`
query($filter: [JobFilter!]!, $rows: Int!, $cols: Int!, query($filter: [JobFilter!]!, $rows: Int!, $cols: Int!,
$minX: Float!, $minY: Float!, $maxX: Float!, $maxY: Float!) { $minX: Float!, $minY: Float!, $maxX: Float!, $maxY: Float!) {
rooflineHeatmap(filter: $filter, rows: $rows, cols: $cols, rooflineHeatmap(filter: $filter, rows: $rows, cols: $cols,
minX: $minX, minY: $minY, maxX: $maxX, maxY: $maxY) minX: $minX, minY: $minY, maxX: $maxX, maxY: $maxY)
} }
`, { `,
filter: [], variables: { filter: [], rows: 50, cols: 50, minX: 0.01, minY: 1., maxX: 1000., maxY: -1. },
rows: 50, cols: 50, pause: true
minX: 0.01, minY: 1., maxX: 1000., maxY: -1. })
}, { pause: true });
query(statsQuery)
query(footprintsQuery)
query(rooflineQuery)
onMount(() => filters.update()) onMount(() => filters.update())
</script> </script>

View File

@ -2,22 +2,28 @@
@component List of users or projects @component List of users or projects
--> -->
<script> <script>
import { onMount } from 'svelte' import { onMount } from "svelte";
import { init } from './utils.js' import { init } from "./utils.js";
import { Row, Col, Button, Icon, Table, Card, Spinner, import { Row, Col, Button, Icon, Table,
InputGroup, Input } from 'sveltestrap' Card, Spinner, InputGroup, Input, } from "sveltestrap";
import Filters from './filters/Filters.svelte' import Filters from "./filters/Filters.svelte";
import { operationStore, query } from '@urql/svelte'; import { queryStore, gql, getContextClient } from "@urql/svelte";
import { scramble, scrambleNames } from './joblist/JobInfo.svelte' import { scramble, scrambleNames } from "./joblist/JobInfo.svelte";
const { } = init() const {} = init();
export let type export let type;
export let filterPresets export let filterPresets;
console.assert(type == 'USER' || type == 'PROJECT', 'Invalid list type provided!') console.assert(
type == "USER" || type == "PROJECT",
"Invalid list type provided!"
);
const stats = operationStore(`query($filter: [JobFilter!]!) { const stats = queryStore({
client: getContextClient(),
query: gql`
query($filter: [JobFilter!]!) {
rows: jobsStatistics(filter: $filter, groupBy: ${type}) { rows: jobsStatistics(filter: $filter, groupBy: ${type}) {
id id
name name
@ -25,41 +31,39 @@
totalWalltime totalWalltime
totalCoreHours totalCoreHours
} }
}`, { }`,
filter: [] variables: { filter, type },
}, { });
pause: true
})
query(stats) let filters;
let nameFilter = "";
let filters let sorting = { field: "totalJobs", direction: "down" };
let nameFilter = ''
let sorting = { field: 'totalJobs', direction: 'down' }
function changeSorting(event, field) { function changeSorting(event, field) {
let target = event.target let target = event.target;
while (target.tagName != 'BUTTON') while (target.tagName != "BUTTON") target = target.parentElement;
target = target.parentElement
let direction = target.children[0].className.includes('up') ? 'down' : 'up' let direction = target.children[0].className.includes("up")
target.children[0].className = `bi-sort-numeric-${direction}` ? "down"
sorting = { field, direction } : "up";
target.children[0].className = `bi-sort-numeric-${direction}`;
sorting = { field, direction };
} }
function sort(stats, sorting, nameFilter) { function sort(stats, sorting, nameFilter) {
const cmp = sorting.field == 'id' const cmp =
? (sorting.direction == 'up' sorting.field == "id"
? (a, b) => a.id < b.id ? sorting.direction == "up"
: (a, b) => a.id > b.id) ? (a, b) => a.id < b.id
: (sorting.direction == 'up' : (a, b) => a.id > b.id
: sorting.direction == "up"
? (a, b) => a[sorting.field] - b[sorting.field] ? (a, b) => a[sorting.field] - b[sorting.field]
: (a, b) => b[sorting.field] - a[sorting.field]) : (a, b) => b[sorting.field] - a[sorting.field];
return stats.filter(u => u.id.includes(nameFilter)).sort(cmp) return stats.filter((u) => u.id.includes(nameFilter)).sort(cmp);
} }
onMount(() => filters.update()) onMount(() => filters.update());
</script> </script>
<Row> <Row>
@ -68,59 +72,85 @@
<Button disabled outline> <Button disabled outline>
Search {type.toLowerCase()}s Search {type.toLowerCase()}s
</Button> </Button>
<Input bind:value={nameFilter} placeholder="Filter by {({ USER: 'username', PROJECT: 'project' })[type]}" /> <Input
bind:value={nameFilter}
placeholder="Filter by {{
USER: 'username',
PROJECT: 'project',
}[type]}"
/>
</InputGroup> </InputGroup>
</Col> </Col>
<Col xs="auto"> <Col xs="auto">
<Filters <Filters
bind:this={filters} bind:this={filters}
filterPresets={filterPresets} {filterPresets}
startTimeQuickSelect={true} startTimeQuickSelect={true}
menuText="Only {type.toLowerCase()}s with jobs that match the filters will show up" menuText="Only {type.toLowerCase()}s with jobs that match the filters will show up"
on:update={({ detail }) => { on:update={({ detail }) => {
$stats.variables = { filter: detail.filters } $stats.variables = { filter: detail.filters };
$stats.context.pause = false $stats.context.pause = false;
$stats.reexecute() $stats.reexecute();
}} /> }}
/>
</Col> </Col>
</Row> </Row>
<Table> <Table>
<thead> <thead>
<tr> <tr>
<th scope="col"> <th scope="col">
{({ USER: 'Username', PROJECT: 'Project Name' })[type]} {({ USER: "Username", PROJECT: "Project Name" })[type]}
<Button color="{sorting.field == 'id' ? 'primary' : 'light'}" <Button
size="sm" on:click={e => changeSorting(e, 'id')}> color={sorting.field == "id" ? "primary" : "light"}
size="sm"
on:click={(e) => changeSorting(e, "id")}
>
<Icon name="sort-numeric-down" /> <Icon name="sort-numeric-down" />
</Button> </Button>
</th> </th>
{#if type == 'USER'} {#if type == "USER"}
<th scope="col"> <th scope="col">
Name Name
<Button color="{sorting.field == 'name' ? 'primary' : 'light'}" <Button
size="sm" on:click={e => changeSorting(e, 'name')}> color={sorting.field == "name" ? "primary" : "light"}
size="sm"
on:click={(e) => changeSorting(e, "name")}
>
<Icon name="sort-numeric-down" /> <Icon name="sort-numeric-down" />
</Button> </Button>
</th> </th>
{/if} {/if}
<th scope="col"> <th scope="col">
Total Jobs Total Jobs
<Button color="{sorting.field == 'totalJobs' ? 'primary' : 'light'}" <Button
size="sm" on:click={e => changeSorting(e, 'totalJobs')}> color={sorting.field == "totalJobs" ? "primary" : "light"}
size="sm"
on:click={(e) => changeSorting(e, "totalJobs")}
>
<Icon name="sort-numeric-down" /> <Icon name="sort-numeric-down" />
</Button> </Button>
</th> </th>
<th scope="col"> <th scope="col">
Total Walltime Total Walltime
<Button color="{sorting.field == 'totalWalltime' ? 'primary' : 'light'}" <Button
size="sm" on:click={e => changeSorting(e, 'totalWalltime')}> color={sorting.field == "totalWalltime"
? "primary"
: "light"}
size="sm"
on:click={(e) => changeSorting(e, "totalWalltime")}
>
<Icon name="sort-numeric-down" /> <Icon name="sort-numeric-down" />
</Button> </Button>
</th> </th>
<th scope="col"> <th scope="col">
Total Core Hours Total Core Hours
<Button color="{sorting.field == 'totalCoreHours' ? 'primary' : 'light'}" <Button
size="sm" on:click={e => changeSorting(e, 'totalCoreHours')}> color={sorting.field == "totalCoreHours"
? "primary"
: "light"}
size="sm"
on:click={(e) => changeSorting(e, "totalCoreHours")}
>
<Icon name="sort-numeric-down" /> <Icon name="sort-numeric-down" />
</Button> </Button>
</th> </th>
@ -129,26 +159,36 @@
<tbody> <tbody>
{#if $stats.fetching} {#if $stats.fetching}
<tr> <tr>
<td colspan="4" style="text-align: center;"><Spinner secondary/></td> <td colspan="4" style="text-align: center;"
><Spinner secondary /></td
>
</tr> </tr>
{:else if $stats.error} {:else if $stats.error}
<tr> <tr>
<td colspan="4"><Card body color="danger" class="mb-3">{$stats.error.message}</Card></td> <td colspan="4"
><Card body color="danger" class="mb-3"
>{$stats.error.message}</Card
></td
>
</tr> </tr>
{:else if $stats.data} {:else if $stats.data}
{#each sort($stats.data.rows, sorting, nameFilter) as row (row.id)} {#each sort($stats.data.rows, sorting, nameFilter) as row (row.id)}
<tr> <tr>
<td> <td>
{#if type == 'USER'} {#if type == "USER"}
<a href="/monitoring/user/{row.id}">{scrambleNames ? scramble(row.id) : row.id}</a> <a href="/monitoring/user/{row.id}"
{:else if type == 'PROJECT'} >{scrambleNames ? scramble(row.id) : row.id}</a
<a href="/monitoring/jobs/?project={row.id}">{row.id}</a> >
{:else if type == "PROJECT"}
<a href="/monitoring/jobs/?project={row.id}"
>{row.id}</a
>
{:else} {:else}
{row.id} {row.id}
{/if} {/if}
</td> </td>
{#if type == 'USER'} {#if type == "USER"}
<td>{row?.name ? row.name : ''}</td> <td>{row?.name ? row.name : ""}</td>
{/if} {/if}
<td>{row.totalJobs}</td> <td>{row.totalJobs}</td>
<td>{row.totalWalltime}</td> <td>{row.totalWalltime}</td>
@ -156,7 +196,9 @@
</tr> </tr>
{:else} {:else}
<tr> <tr>
<td colspan="4"><i>No {type.toLowerCase()}s/jobs found</i></td> <td colspan="4"
><i>No {type.toLowerCase()}s/jobs found</i></td
>
</tr> </tr>
{/each} {/each}
{/if} {/if}

View File

@ -10,7 +10,7 @@
<script> <script>
import { Modal, ModalBody, ModalHeader, ModalFooter, Button, ListGroup } from 'sveltestrap' import { Modal, ModalBody, ModalHeader, ModalFooter, Button, ListGroup } from 'sveltestrap'
import { getContext } from 'svelte' import { getContext } from 'svelte'
import { mutation } from '@urql/svelte' import { gql, getContextClient , mutationStore } from '@urql/svelte'
export let metrics export let metrics
export let isOpen export let isOpen
@ -53,11 +53,15 @@
} }
} }
const updateConfiguration = mutation({ const updateConfiguration = ({ name, value }) => {
query: `mutation($name: String!, $value: String!) { result = mutationStore({
client: getContextClient(),
query: gql`mutation($name: String!, $value: String!) {
updateConfiguration(name: $name, value: $value) updateConfiguration(name: $name, value: $value)
}` }`,
variables: {name, value}
}) })
}
let columnHovering = null let columnHovering = null

View File

@ -1,7 +1,7 @@
<script> <script>
import { init } from './utils.js' import { init } from './utils.js'
import { Row, Col, InputGroup, InputGroupText, Icon, Spinner, Card } from 'sveltestrap' import { Row, Col, InputGroup, InputGroupText, Icon, Spinner, Card } from 'sveltestrap'
import { operationStore, query } from '@urql/svelte' import { queryStore, gql, getContextClient } from '@urql/svelte'
import TimeSelection from './filters/TimeSelection.svelte' import TimeSelection from './filters/TimeSelection.svelte'
import PlotTable from './PlotTable.svelte' import PlotTable from './PlotTable.svelte'
import MetricPlot from './plots/MetricPlot.svelte' import MetricPlot from './plots/MetricPlot.svelte'
@ -23,7 +23,9 @@
const ccconfig = getContext('cc-config') const ccconfig = getContext('cc-config')
const clusters = getContext('clusters') const clusters = getContext('clusters')
const nodesQuery = operationStore(`query($cluster: String!, $nodes: [String!], $from: Time!, $to: Time!) { const nodesQuery = queryStore({
client: getContextClient(),
query: gql`query($cluster: String!, $nodes: [String!], $from: Time!, $to: Time!) {
nodeMetrics(cluster: $cluster, nodes: $nodes, from: $from, to: $to) { nodeMetrics(cluster: $cluster, nodes: $nodes, from: $from, to: $to) {
host host
subCluster subCluster
@ -40,11 +42,12 @@
} }
} }
} }
}`, { }`,
variables: {
cluster: cluster, cluster: cluster,
nodes: [hostname], nodes: [hostname],
from: from.toISOString(), from: from.toISOString(),
to: to.toISOString() to: to.toISOString() }
}) })
$: $nodesQuery.variables = { cluster, nodes: [hostname], from: from.toISOString(), to: to.toISOString() } $: $nodesQuery.variables = { cluster, nodes: [hostname], from: from.toISOString(), to: to.toISOString() }
@ -59,9 +62,6 @@
} }
} }
} }
query(nodesQuery)
// $: console.log($nodesQuery?.data?.nodeMetrics[0].metrics) // $: console.log($nodesQuery?.data?.nodeMetrics[0].metrics)
</script> </script>

View File

@ -1,17 +1,21 @@
<script> <script>
import { Modal, ModalBody, ModalHeader, ModalFooter, InputGroup, import { Modal, ModalBody, ModalHeader, ModalFooter, InputGroup,
Button, ListGroup, ListGroupItem, Icon } from 'sveltestrap' Button, ListGroup, ListGroupItem, Icon } from 'sveltestrap'
import { mutation } from '@urql/svelte' import { gql, getContextClient , mutationStore } from '@urql/svelte'
export let availableMetrics export let availableMetrics
export let metricsInHistograms export let metricsInHistograms
export let metricsInScatterplots export let metricsInScatterplots
const updateConfigurationMutation = mutation({ const updateConfigurationMutation = ({ name, value }) => {
query: `mutation($name: String!, $value: String!) { result = mutationStore({
client: getContextClient(),
query: gql`mutation($name: String!, $value: String!) {
updateConfiguration(name: $name, value: $value) updateConfiguration(name: $name, value: $value)
}` }`,
variables: { name, value }
}) })
}
let isHistogramConfigOpen = false, isScatterPlotConfigOpen = false let isHistogramConfigOpen = false, isScatterPlotConfigOpen = false
let selectedMetric1 = null, selectedMetric2 = null let selectedMetric1 = null, selectedMetric2 = null

View File

@ -4,7 +4,7 @@
import Histogram from './plots/Histogram.svelte' import Histogram from './plots/Histogram.svelte'
import { Row, Col, Spinner, Card, CardHeader, CardTitle, CardBody, Table, Progress, Icon } from 'sveltestrap' import { Row, Col, Spinner, Card, CardHeader, CardTitle, CardBody, Table, Progress, Icon } from 'sveltestrap'
import { init } from './utils.js' import { init } from './utils.js'
import { operationStore, query } from '@urql/svelte' import { queryStore, gql, getContextClient } from '@urql/svelte'
const { query: initq } = init() const { query: initq } = init()
@ -13,7 +13,9 @@
let plotWidths = [], colWidth1 = 0, colWidth2 let plotWidths = [], colWidth1 = 0, colWidth2
let from = new Date(Date.now() - 5 * 60 * 1000), to = new Date(Date.now()) let from = new Date(Date.now() - 5 * 60 * 1000), to = new Date(Date.now())
const mainQuery = operationStore(`query($cluster: String!, $filter: [JobFilter!]!, $metrics: [String!], $from: Time!, $to: Time!) { const mainQuery = queryStore({
client: getContextClient(),
query: gql`query($cluster: String!, $filter: [JobFilter!]!, $metrics: [String!], $from: Time!, $to: Time!) {
nodeMetrics(cluster: $cluster, metrics: $metrics, from: $from, to: $to) { nodeMetrics(cluster: $cluster, metrics: $metrics, from: $from, to: $to) {
host host
subCluster subCluster
@ -36,12 +38,11 @@
allocatedNodes(cluster: $cluster) { name, count } allocatedNodes(cluster: $cluster) { name, count }
topUsers: jobsCount(filter: $filter, groupBy: USER, weight: NODE_COUNT, limit: 10) { name, count } topUsers: jobsCount(filter: $filter, groupBy: USER, weight: NODE_COUNT, limit: 10) { name, count }
topProjects: jobsCount(filter: $filter, groupBy: PROJECT, weight: NODE_COUNT, limit: 10) { name, count } topProjects: jobsCount(filter: $filter, groupBy: PROJECT, weight: NODE_COUNT, limit: 10) { name, count }
}`, { }`,
cluster: cluster, variables: {
metrics: ['flops_any', 'mem_bw'], cluster: cluster, metrics: ['flops_any', 'mem_bw'], from: from.toISOString(), to: to.toISOString(),
from: from.toISOString(),
to: to.toISOString(),
filter: [{ state: ['running'] }, { cluster: { eq: cluster } }] filter: [{ state: ['running'] }, { cluster: { eq: cluster } }]
}
}) })
const sumUp = (data, subcluster, metric) => data.reduce((sum, node) => node.subCluster == subcluster const sumUp = (data, subcluster, metric) => data.reduce((sum, node) => node.subCluster == subcluster

View File

@ -1,7 +1,7 @@
<script> <script>
import { init } from './utils.js' import { init } from './utils.js'
import { Row, Col, Input, InputGroup, InputGroupText, Icon, Spinner, Card } from 'sveltestrap' import { Row, Col, Input, InputGroup, InputGroupText, Icon, Spinner, Card } from 'sveltestrap'
import { operationStore, query } from '@urql/svelte' import { queryStore, gql, getContextClient } from '@urql/svelte'
import TimeSelection from './filters/TimeSelection.svelte' import TimeSelection from './filters/TimeSelection.svelte'
import PlotTable from './PlotTable.svelte' import PlotTable from './PlotTable.svelte'
import MetricPlot from './plots/MetricPlot.svelte' import MetricPlot from './plots/MetricPlot.svelte'
@ -27,7 +27,9 @@
let hostnameFilter = '' let hostnameFilter = ''
let selectedMetric = ccconfig.system_view_selectedMetric let selectedMetric = ccconfig.system_view_selectedMetric
const nodesQuery = operationStore(`query($cluster: String!, $metrics: [String!], $from: Time!, $to: Time!) { const nodesQuery = queryStore({
client: getContextClient(),
query: gql`query($cluster: String!, $metrics: [String!], $from: Time!, $to: Time!) {
nodeMetrics(cluster: $cluster, metrics: $metrics, from: $from, to: $to) { nodeMetrics(cluster: $cluster, metrics: $metrics, from: $from, to: $to) {
host host
subCluster subCluster
@ -44,11 +46,12 @@
} }
} }
} }
}`, { }`,
variables: {
cluster: cluster, cluster: cluster,
metrics: [], metrics: [],
from: from.toISOString(), from: from.toISOString(),
to: to.toISOString() to: to.toISOString()}
}) })
let metricUnits = {} let metricUnits = {}
@ -64,8 +67,6 @@
} }
$: $nodesQuery.variables = { cluster, metrics: [selectedMetric], from: from.toISOString(), to: to.toISOString() } $: $nodesQuery.variables = { cluster, metrics: [selectedMetric], from: from.toISOString(), to: to.toISOString() }
query(nodesQuery)
</script> </script>
<Row> <Row>

View File

@ -1,6 +1,6 @@
<script> <script>
import { getContext } from 'svelte' import { getContext } from 'svelte'
import { mutation } from '@urql/svelte' import { gql, getContextClient , mutationStore } from '@urql/svelte'
import { Icon, Button, ListGroupItem, Spinner, Modal, Input, import { Icon, Button, ListGroupItem, Spinner, Modal, Input,
ModalBody, ModalHeader, ModalFooter, Alert } from 'sveltestrap' ModalBody, ModalHeader, ModalFooter, Alert } from 'sveltestrap'
import { fuzzySearchTags } from './utils.js' import { fuzzySearchTags } from './utils.js'
@ -15,23 +15,34 @@
let pendingChange = false let pendingChange = false
let isOpen = false let isOpen = false
const createTagMutation = mutation({ const createTagMutation = ({ type, name }) => {
query: `mutation($type: String!, $name: String!) { result = mutationStore({
client: getContextClient(),
query: gql`mutation($type: String!, $name: String!) {
createTag(type: $type, name: $name) { id, type, name } createTag(type: $type, name: $name) { id, type, name }
}` }`,
variables: { type, name}
}) })
}
const addTagsToJobMutation = mutation({ const addTagsToJobMutation = ({ job, tagIds }) => {
query: `mutation($job: ID!, $tagIds: [ID!]!) { result = mutationStore({
client: getContextClient(),
query: gql`mutation($job: ID!, $tagIds: [ID!]!) {
addTagsToJob(job: $job, tagIds: $tagIds) { id, type, name } addTagsToJob(job: $job, tagIds: $tagIds) { id, type, name }
}` }`,
variables: {job, tagIds}
}) })
}
const removeTagsFromJobMutation = mutation({ const removeTagsFromJobMutation = ({ job, tagIds }) => {
query: `mutation($job: ID!, $tagIds: [ID!]!) { result = mutationStore({
client: getContextClient(),
query: gql`mutation($job: ID!, $tagIds: [ID!]!) {
removeTagsFromJob(job: $job, tagIds: $tagIds) { id, type, name } removeTagsFromJob(job: $job, tagIds: $tagIds) { id, type, name }
}` }`
}) })
}
let allTagsFiltered // $initialized is in there because when it becomes true, allTags is initailzed. let allTagsFiltered // $initialized is in there because when it becomes true, allTags is initailzed.
$: allTagsFiltered = ($initialized, fuzzySearchTags(filterTerm, allTags)) $: allTagsFiltered = ($initialized, fuzzySearchTags(filterTerm, allTags))

View File

@ -2,7 +2,7 @@
import { onMount, getContext } from 'svelte' import { onMount, getContext } from 'svelte'
import { init } from './utils.js' import { init } from './utils.js'
import { Table, Row, Col, Button, Icon, Card, Spinner } from 'sveltestrap' import { Table, Row, Col, Button, Icon, Card, Spinner } from 'sveltestrap'
import { operationStore, query } from '@urql/svelte' import { queryStore, gql, getContextClient } from '@urql/svelte'
import Filters from './filters/Filters.svelte' import Filters from './filters/Filters.svelte'
import JobList from './joblist/JobList.svelte' import JobList from './joblist/JobList.svelte'
import Sorting from './joblist/SortSelection.svelte' import Sorting from './joblist/SortSelection.svelte'
@ -25,8 +25,10 @@
let w1, w2, histogramHeight = 250 let w1, w2, histogramHeight = 250
let selectedCluster = filterPresets?.cluster ? filterPresets.cluster : null let selectedCluster = filterPresets?.cluster ? filterPresets.cluster : null
const stats = operationStore(` const stats = queryStore({
query($filter: [JobFilter!]!) { client: getContextClient(),
query: gql`
query($filter: [JobFilter!]!) {
jobsStatistics(filter: $filter) { jobsStatistics(filter: $filter) {
totalJobs totalJobs
shortJobs shortJobs
@ -35,10 +37,10 @@
histDuration { count, value } histDuration { count, value }
histNumNodes { count, value } histNumNodes { count, value }
} }
} }`,
`, { variables: {
filter: [] filter: []
}, { },
pause: true pause: true
}) })

View File

@ -9,7 +9,7 @@
- update(filters?: [JobFilter]) - update(filters?: [JobFilter])
--> -->
<script> <script>
import { operationStore, query, mutation } from '@urql/svelte' import { queryStore, gql, getContextClient , mutationStore } from '@urql/svelte'
import { getContext } from 'svelte'; import { getContext } from 'svelte';
import { Row, Table, Card, Spinner } from 'sveltestrap' import { Row, Table, Card, Spinner } from 'sveltestrap'
import Pagination from './Pagination.svelte' import Pagination from './Pagination.svelte'
@ -29,11 +29,13 @@
let paging = { itemsPerPage, page } let paging = { itemsPerPage, page }
let filter = [] let filter = []
const jobs = operationStore(` const jobs = queryStore({
query($filter: [JobFilter!]!, $sorting: OrderByInput!, $paging: PageRequest! ){ client: getContextClient(),
jobs(filter: $filter, order: $sorting, page: $paging) { query: gql`
items { query($filter: [JobFilter!]!, $sorting: OrderByInput!, $paging: PageRequest! ){
id, jobId, user, project, jobName, cluster, subCluster, startTime, jobs(filter: $filter, order: $sorting, page: $paging) {
items {
id, jobId, user, project, jobName, cluster, subCluster, startTime,
duration, numNodes, numHWThreads, numAcc, walltime, resources { hostname }, duration, numNodes, numHWThreads, numAcc, walltime, resources { hostname },
SMT, exclusive, partition, arrayJobId, SMT, exclusive, partition, arrayJobId,
monitoringStatus, state, monitoringStatus, state,
@ -43,19 +45,20 @@
} }
count count
} }
}`, { }`,
paging, variables: { paging, sorting, filter },
sorting, pause: true
filter,
}, {
pause: true
}) })
const updateConfiguration = mutation({ const updateConfiguration = ({ name, value }) => {
query: `mutation($name: String!, $value: String!) { result = mutationStore({
client: getContextClient(),
query: gql`mutation($name: String!, $value: String!) {
updateConfiguration(name: $name, value: $value) updateConfiguration(name: $name, value: $value)
}` }`,
variables: {name, value}
}) })
}
$: $jobs.variables = { ...$jobs.variables, sorting, paging } $: $jobs.variables = { ...$jobs.variables, sorting, paging }
$: matchedJobs = $jobs.data != null ? $jobs.data.jobs.count : 0 $: matchedJobs = $jobs.data != null ? $jobs.data.jobs.count : 0

View File

@ -9,7 +9,7 @@
--> -->
<script> <script>
import { operationStore, query } from '@urql/svelte' import { queryStore, gql, getContextClient } from '@urql/svelte'
import { getContext } from 'svelte' import { getContext } from 'svelte'
import { Card, Spinner } from 'sveltestrap' import { Card, Spinner } from 'sveltestrap'
import MetricPlot from '../plots/MetricPlot.svelte' import MetricPlot from '../plots/MetricPlot.svelte'
@ -26,7 +26,10 @@
const cluster = getContext('clusters').find(c => c.name == job.cluster) const cluster = getContext('clusters').find(c => c.name == job.cluster)
// Get all MetricConfs which include subCluster-specific settings for this job // Get all MetricConfs which include subCluster-specific settings for this job
const metricConfig = getContext('metrics') const metricConfig = getContext('metrics')
const metricsQuery = operationStore(`query($id: ID!, $metrics: [String!]!, $scopes: [MetricScope!]!) { const metricsQuery = queryStore({
client: getContextClient(),
query: gql`
query($id: ID!, $metrics: [String!]!, $scopes: [MetricScope!]!) {
jobMetrics(id: $id, metrics: $metrics, scopes: $scopes) { jobMetrics(id: $id, metrics: $metrics, scopes: $scopes) {
name name
scope scope
@ -39,10 +42,12 @@
} }
} }
} }
}`, { }`,
pause: true,
variables: {
id: job.id, id: job.id,
metrics, metrics,
scopes scopes}
}) })
const selectScope = (jobMetrics) => jobMetrics.reduce( const selectScope = (jobMetrics) => jobMetrics.reduce(
@ -91,7 +96,7 @@
$: metricsQuery.variables = { id: job.id, metrics, scopes } $: metricsQuery.variables = { id: job.id, metrics, scopes }
if (job.monitoringStatus) if (job.monitoringStatus)
query(metricsQuery) $metricsQuery.resume()
</script> </script>
<tr> <tr>

View File

@ -1,5 +1,5 @@
import { expiringCacheExchange } from './cache-exchange.js' import { expiringCacheExchange } from './cache-exchange.js'
import { Client, fetchExchange } from '@urql/svelte'; import { Client, setContextClient, fetchExchange } from '@urql/svelte';
import { setContext, getContext, hasContext, onDestroy, tick } from 'svelte' import { setContext, getContext, hasContext, onDestroy, tick } from 'svelte'
import { readable } from 'svelte/store' import { readable } from 'svelte/store'
@ -32,6 +32,8 @@ export function init(extraInitQuery = '') {
] ]
}) })
setContextClient(client)
const query = client.query(`query { const query = client.query(`query {
clusters { clusters {
name, name,