summaryrefslogtreecommitdiffhomepage
path: root/src/features/concurrency/logic
diff options
context:
space:
mode:
authorAdam Malczewski <[email protected]>2026-06-28 20:25:51 +0900
committerAdam Malczewski <[email protected]>2026-06-28 20:25:51 +0900
commit3b71b63c29a4a7cdc67fd52e08310aa34731ab82 (patch)
tree3219b63bceac5e4073676c633d8abf596c143b38 /src/features/concurrency/logic
parentb22c6c6e897fc8ad48c6a21c8034973f40a5f1a1 (diff)
downloaddispatch-web-3b71b63c29a4a7cdc67fd52e08310aa34731ab82.tar.gz
dispatch-web-3b71b63c29a4a7cdc67fd52e08310aa34731ab82.zip
fix(concurrency): Set+X on same line, status line with in-flight count and badge
Diffstat (limited to 'src/features/concurrency/logic')
-rw-r--r--src/features/concurrency/logic/view-model.test.ts37
-rw-r--r--src/features/concurrency/logic/view-model.ts13
2 files changed, 50 insertions, 0 deletions
diff --git a/src/features/concurrency/logic/view-model.test.ts b/src/features/concurrency/logic/view-model.test.ts
index c284ad0..6e6b770 100644
--- a/src/features/concurrency/logic/view-model.test.ts
+++ b/src/features/concurrency/logic/view-model.test.ts
@@ -14,6 +14,7 @@ import {
pauseLabel,
providerFromModel,
providerOptions,
+ statusLabel,
summarizeLimits,
summarizeStatus,
viewAutoReduce,
@@ -262,6 +263,42 @@ describe("viewConcurrencyStatus", () => {
});
});
+// ── statusLabel (the row's status badge word) ──────────────────────────────────
+
+describe("statusLabel", () => {
+ it("idle (no in-flight) → Idle", () => {
+ expect(
+ statusLabel(viewConcurrencyStatus(status({ inFlight: 0, limit: 4, queued: 0 }), 0)),
+ ).toBe("Idle");
+ });
+
+ it("serving under capacity → Active", () => {
+ expect(
+ statusLabel(viewConcurrencyStatus(status({ inFlight: 2, limit: 4, queued: 0 }), 0)),
+ ).toBe("Active");
+ });
+
+ it("at capacity with a queue → At capacity", () => {
+ expect(
+ statusLabel(viewConcurrencyStatus(status({ inFlight: 4, limit: 4, queued: 3 }), 0)),
+ ).toBe("At capacity");
+ });
+
+ it("at capacity but no queue → Active (not At capacity)", () => {
+ expect(
+ statusLabel(viewConcurrencyStatus(status({ inFlight: 4, limit: 4, queued: 0 }), 0)),
+ ).toBe("Active");
+ });
+
+ it("paused → Paused (regardless of in-flight/queue)", () => {
+ expect(
+ statusLabel(
+ viewConcurrencyStatus(status({ paused: true, inFlight: 4, limit: 4, queued: 3 }), 0),
+ ),
+ ).toBe("Paused");
+ });
+});
+
// ── viewAutoReduce / autoReduceNotices (the auto-reduce banner view) ───────────
describe("viewAutoReduce", () => {
diff --git a/src/features/concurrency/logic/view-model.ts b/src/features/concurrency/logic/view-model.ts
index e05423b..8a37198 100644
--- a/src/features/concurrency/logic/view-model.ts
+++ b/src/features/concurrency/logic/view-model.ts
@@ -261,6 +261,19 @@ export function viewConcurrencyStatus(
}
/**
+ * A short status word for a status view, for the row's status badge:
+ * "Paused" · "At capacity" (in-flight at the cap with a queue) · "Active"
+ * (in-flight > 0) · "Idle". Mirrors the badge-text branching so the template
+ * holds no branching logic.
+ */
+export function statusLabel(view: ConcurrencyStatusView): string {
+ if (view.paused) return "Paused";
+ if (view.inFlight >= view.limit && view.queued > 0) return "At capacity";
+ if (view.inFlight > 0) return "Active";
+ return "Idle";
+}
+
+/**
* The auto-reduce banner view for a status entry, or `null` when it is not
* auto-reduced. `message` prefers the backend's `notice` (verbatim, when present
* + non-empty); otherwise a synthesized fallback is built from