Write a run's elapsed time once, in the duration formatter's units
The runs table drew when a run started and how long it took in two
notations ('56m ago | 55.5 min'), and for a run still going those are the
same reading twice. `dur` now steps past the minute into hours and days,
the ago reading is derived from it, and a running run writes only the
elapsed one.
This commit is contained in:
@@ -6,7 +6,6 @@ import { useRef } from "react"
|
|||||||
import type { fluksio__api__routes__runs__RunRow as RunRow } from "@/client"
|
import type { fluksio__api__routes__runs__RunRow as RunRow } from "@/client"
|
||||||
import { MAX_SERIES } from "@/components/Common/UplotChart"
|
import { MAX_SERIES } from "@/components/Common/UplotChart"
|
||||||
import { ValuePreview } from "@/components/Flow/ValuePreview"
|
import { ValuePreview } from "@/components/Flow/ValuePreview"
|
||||||
import { ago } from "@/components/Health/queries"
|
|
||||||
import { Button } from "@/components/ui/button"
|
import { Button } from "@/components/ui/button"
|
||||||
import { Checkbox } from "@/components/ui/checkbox"
|
import { Checkbox } from "@/components/ui/checkbox"
|
||||||
import {
|
import {
|
||||||
@@ -296,6 +295,12 @@ function ParamValue({ value }: { value: unknown }) {
|
|||||||
return <span className="font-mono text-xs">{paramText(value)}</span>
|
return <span className="font-mono text-xs">{paramText(value)}</span>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** How long ago a moment was, in `dur`'s units so a row's two times agree. */
|
||||||
|
function since(ts: unknown): string {
|
||||||
|
if (!ts) return "—"
|
||||||
|
return `${dur(Date.now() - Date.parse(String(ts)))} ago`
|
||||||
|
}
|
||||||
|
|
||||||
function RunsTable({
|
function RunsTable({
|
||||||
runs,
|
runs,
|
||||||
search,
|
search,
|
||||||
@@ -456,14 +461,20 @@ function RunsTable({
|
|||||||
only the store's, which is then the whole answer. */}
|
only the store's, which is then the whole answer. */}
|
||||||
{shortCommit(run.origin_commit || run.commit || "") || "—"}
|
{shortCommit(run.origin_commit || run.commit || "") || "—"}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell className="whitespace-nowrap text-muted-foreground text-sm">
|
<TableCell className="whitespace-nowrap text-muted-foreground text-sm tabular-nums">
|
||||||
{/* When it started, and how long it then took. Two readings of
|
{/* When it started, and how long it then took. Two readings of
|
||||||
one thing, so one column rather than two. */}
|
one thing, so one column rather than two — and while a run is
|
||||||
{ago(String(run.created_at ?? ""))}
|
still going they are the same reading, so it is written once:
|
||||||
<span className="px-1.5 text-border">|</span>
|
how long it has been running is also how long ago it began. */}
|
||||||
<span className="tabular-nums">
|
{run.status === "running" ? (
|
||||||
{run.duration_ms ? dur(run.duration_ms) : "—"}
|
`${dur(run.duration_ms)} ago`
|
||||||
</span>
|
) : (
|
||||||
|
<>
|
||||||
|
{since(run.created_at)}
|
||||||
|
<span className="px-1.5 text-border">|</span>
|
||||||
|
<span>{run.duration_ms ? dur(run.duration_ms) : "—"}</span>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -38,6 +38,8 @@ assert.equal(dur(0), "0 ms")
|
|||||||
assert.equal(dur(203.63), "204 ms")
|
assert.equal(dur(203.63), "204 ms")
|
||||||
assert.equal(dur(1240), "1.24 s")
|
assert.equal(dur(1240), "1.24 s")
|
||||||
assert.equal(dur(90_000), "1.5 min")
|
assert.equal(dur(90_000), "1.5 min")
|
||||||
|
assert.equal(dur(12_600_000), "3.5 h")
|
||||||
|
assert.equal(dur(259_200_000), "3 d")
|
||||||
|
|
||||||
// The plain window down to 0.01 ms, so a fast run keeps one unit across polls.
|
// The plain window down to 0.01 ms, so a fast run keeps one unit across polls.
|
||||||
assert.equal(dur(0.4), "0.4 ms")
|
assert.equal(dur(0.4), "0.4 ms")
|
||||||
|
|||||||
@@ -44,6 +44,8 @@ export function si(value: number, digits = 3): string {
|
|||||||
|
|
||||||
/** Floor, divisor and unit per step, largest first. */
|
/** Floor, divisor and unit per step, largest first. */
|
||||||
const DUR_STEPS: [number, number, string][] = [
|
const DUR_STEPS: [number, number, string][] = [
|
||||||
|
[86_400_000, 86_400_000, "d"],
|
||||||
|
[3_600_000, 3_600_000, "h"],
|
||||||
[60_000, 60_000, "min"],
|
[60_000, 60_000, "min"],
|
||||||
[1_000, 1_000, "s"],
|
[1_000, 1_000, "s"],
|
||||||
[0.01, 1, "ms"],
|
[0.01, 1, "ms"],
|
||||||
@@ -63,6 +65,9 @@ const DUR_STEPS: [number, number, string][] = [
|
|||||||
* window transposed onto units. That floor is deliberate: without it a tile
|
* window transposed onto units. That floor is deliberate: without it a tile
|
||||||
* polled every ten seconds flips between "400 µs" and "1.2 ms", and a reading
|
* polled every ten seconds flips between "400 µs" and "1.2 ms", and a reading
|
||||||
* that changes unit on every poll reads as broken rather than as fast.
|
* that changes unit on every poll reads as broken rather than as fast.
|
||||||
|
*
|
||||||
|
* It keeps stepping past the minute into hours and days, so that an elapsed
|
||||||
|
* time is one notation wherever it is written — "3.5 h", never "210 min".
|
||||||
*/
|
*/
|
||||||
export function dur(ms: number, digits = 3): string {
|
export function dur(ms: number, digits = 3): string {
|
||||||
if (!Number.isFinite(ms)) return "--"
|
if (!Number.isFinite(ms)) return "--"
|
||||||
|
|||||||
Reference in New Issue
Block a user