Commit b91fb05e authored by Hines, Jesse's avatar Hines, Jesse
Browse files

Handle large job lists

parent 0db1c3a8
Loading
Loading
Loading
Loading
+26 −10
Original line number Diff line number Diff line
@@ -7,7 +7,7 @@ import { CDUList } from "../components/simulations/console/cduList";
import { Power } from "../components/simulations/console/power";
import { Scheduler } from "../components/simulations/console/scheduler";
import { Message } from "../components/shared/simulation/message";
import { toDate } from "date-fns";
import { toDate, differenceInSeconds, addSeconds, subSeconds, min as minDate } from "date-fns";
import {
  simulationConfigurationQueryOptions, simulationSystemStatsQueryOptions,
  simulationCoolingCDUQueryOptions, simulationCoolingCEPQueryOptions,
@@ -16,6 +16,7 @@ import {
import { computeJobState } from "../util/jobs";
import { useReplay } from "../util/hooks/useReplay";
import { Job } from "../models/Job.model";
import { floorDate } from "../util/datetime";


export const Route = createFileRoute("/simulations/$simulationId/console")({
@@ -29,7 +30,7 @@ function SimulationConsoleView() {

  const { data: sim } = useQuery(simulationConfigurationQueryOptions(simulationId))

  const { data: schedulerStatistics } = useReplay({
  const { maxTimestamp, data: schedulerStatistics } = useReplay({
    sim: sim,
    query: (params) => simulationSystemStatsQueryOptions(simulationId, params),
    timestamp: currentTimestamp,
@@ -53,22 +54,37 @@ function SimulationConsoleView() {
    summarize: !currentTimestamp,
  })

  const { data: jobs } = useQuery({
  const jobPageSize = search.playbackInterval * 100;
  // how long completed jobs will stay in the chart
  const jobLingerTime = search.playbackInterval * 5
  let jobQueryStart: Date|undefined, jobQueryEnd: Date|undefined;
  if (sim && currentTimestamp && maxTimestamp) {
    jobQueryStart = subSeconds(floorDate(currentTimestamp, jobPageSize, sim.start), jobLingerTime)
    jobQueryEnd = minDate([addSeconds(jobQueryStart, jobPageSize + jobLingerTime), maxTimestamp])
  }

  const { data: jobsRaw } = useQuery({
    ...simulationSchedulerJobs(simulationId, {
      // TODO: should use an "infiniteQuery" or something in case you have a lot of jobs in a simulation
      start: jobQueryStart?.toISOString(), end: jobQueryEnd?.toISOString(),
      limit: 1000,
      fields: [
        'job_id', 'name', 'node_count', 'state_current', 'time_limit', 'time_start', 'time_end',
        'time_submission',
      ],
    }),
    select: (data) => (
      data
        .results
    placeholderData: (prevData, _prevQuery) => prevData,
    staleTime: Infinity, // We're capping queries to maxTimestamp so they should always be valid
  });

  const jobs = (
    jobsRaw?.results
      .map(j => ({...j, state_current: computeJobState(j, currentTimestamp)}))
        .filter(j => j.state_current != "UNSUBMITTED")
      // Filter out unsubmitted jobs, and completed jobs after a few steps
      .filter(j => 
        j.state_current != "UNSUBMITTED" &&
        (!currentTimestamp || !j.time_end || differenceInSeconds(currentTimestamp, j.time_end) > jobLingerTime)
      )
  ) as Job[]
  });

  return (
    <section className="grid min-w-[1024px] grid-cols-12 gap-2 overflow-auto p-2">