Skip to content

Commit 88c6af5

Browse files
Render ready-due queue-latency age on the Waterline dashboard Runnable tasks card
Adds an "oldest ready N waiting (since ISO)" meta line under the existing "delayed, leased" breakdown that reads operator_metrics.tasks.max_ready_due_age_ms and operator_metrics.tasks.oldest_ready_due_at, mirroring the stuck-lease-age meta already rendered on the Unhealthy tasks card. The meta line is gated by operatorReadyDueAgeAvailable() so dashboards backed by workflow packages that predate the ready-due age contract continue to render without the meta. Pins V2DashboardStatsControllerTest::testIndexExposesReadyDueAge for the new operator_metrics.tasks keys. The assertion self-skips when the vendored workflow package predates the contract, matching the stuck-lease-age pattern.
1 parent 79515c6 commit 88c6af5

4 files changed

Lines changed: 69 additions & 2 deletions

File tree

public/app.js

Lines changed: 14 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

public/mix-manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"/app.js": "/app.js?id=f009cb737206d1b42e9dc424606e1a1a",
2+
"/app.js": "/app.js?id=2da3db07039ecaab3c6709cc7c78e192",
33
"/app-dark.css": "/app-dark.css?id=14bdc4fb1d6331a94030dc13821344fb",
44
"/app.css": "/app.css?id=3d56d0e6a90f99083d111a8474a3c271",
55
"/img/favicon.png": "/img/favicon.png?id=7c006241b093796d6abfa3049df93a59",

resources/js/screens/dashboard.vue

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,12 @@
297297
{{ operatorMetricLabel('backlog', 'delayed_tasks') }} delayed,
298298
{{ operatorMetricLabel('backlog', 'leased_tasks') }} leased
299299
</div>
300+
<div v-if="operatorReadyDueAgeAvailable()" class="wl-operator-metric__meta">
301+
oldest ready {{ operatorDurationMetricLabel('tasks', 'max_ready_due_age_ms') }} waiting
302+
<template v-if="operatorReadyDueOldestAt()">
303+
(since {{ operatorReadyDueOldestAt() }})
304+
</template>
305+
</div>
300306
</div>
301307
<div class="wl-operator-metric">
302308
<div class="wl-operator-metric__label">Unhealthy tasks</div>
@@ -1140,6 +1146,24 @@ export default {
11401146
return tasks.oldest_lease_expired_at || null;
11411147
},
11421148
1149+
operatorReadyDueAgeAvailable() {
1150+
const tasks = (this.operatorMetrics && this.operatorMetrics.tasks) || {};
1151+
1152+
if (tasks.max_ready_due_age_ms === undefined
1153+
|| tasks.max_ready_due_age_ms === null) {
1154+
return false;
1155+
}
1156+
1157+
return Number(tasks.ready_due || 0) > 0
1158+
|| Number(tasks.max_ready_due_age_ms || 0) > 0;
1159+
},
1160+
1161+
operatorReadyDueOldestAt() {
1162+
const tasks = (this.operatorMetrics && this.operatorMetrics.tasks) || {};
1163+
1164+
return tasks.oldest_ready_due_at || null;
1165+
},
1166+
11431167
operatorSchedulesAvailable() {
11441168
const schedules = this.operatorMetrics && this.operatorMetrics.schedules;
11451169

tests/Feature/V2DashboardStatsControllerTest.php

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -762,4 +762,34 @@ public function testIndexExposesStuckLeaseAge(): void
762762
'operator_metrics.tasks.max_lease_expired_age_ms must be null or integer milliseconds',
763763
);
764764
}
765+
766+
public function testIndexExposesReadyDueAge(): void
767+
{
768+
config()->set('waterline.engine_source', 'v2');
769+
770+
$response = $this->get('/waterline/api/stats')->assertStatus(200);
771+
772+
$tasks = $response->json('operator_metrics.tasks');
773+
774+
$this->assertIsArray($tasks);
775+
776+
if (! array_key_exists('max_ready_due_age_ms', $tasks)
777+
|| ! array_key_exists('oldest_ready_due_at', $tasks)) {
778+
$this->markTestSkipped(
779+
'Vendored workflow package predates the ready-due age rollout-safety contract '
780+
. '(operator_metrics.tasks.oldest_ready_due_at / max_ready_due_age_ms).',
781+
);
782+
}
783+
784+
$this->assertTrue(
785+
$tasks['oldest_ready_due_at'] === null
786+
|| is_string($tasks['oldest_ready_due_at']),
787+
'operator_metrics.tasks.oldest_ready_due_at must be null or ISO-8601 string',
788+
);
789+
$this->assertTrue(
790+
$tasks['max_ready_due_age_ms'] === null
791+
|| is_int($tasks['max_ready_due_age_ms']),
792+
'operator_metrics.tasks.max_ready_due_age_ms must be null or integer milliseconds',
793+
);
794+
}
765795
}

0 commit comments

Comments
 (0)