Skip to content

Home dashboard: hook up Export jobs, add Import jobs, and settle the data source #554

Description

@smunini

Summary

The Home dashboard's Export jobs card shows a hardcoded number. Hook it up to real job state, add an equivalent Import jobs card, and settle where these figures should come from.

1. Export jobs is not hooked up

crates/ui/src/lib.rs:1367-1379 says so outright:

// Not part of the resource-count read path — placeholder until the bulk
// export job-state and availability read paths are wired.
export_jobs: "13".to_string(),
export_jobs_queued: 1,
uptime_percent: "99.98".to_string(),

So the card at crates/ui/templates/pages/index.html:17-21 always reads "13 / running (1 queued)", on every server, in every tenant.

2. Add an Import jobs card

Bulk Data Submit already has a full UI at /ui/bulk-import (a nav entry at base.html:82), but nothing on the dashboard. Add a card alongside Export jobs, and link it to the existing page.

Note the layout: .stat-grid is repeat(4, 1fr) (app.css:594-599), currently exactly full. A fifth card needs a deliberate layout decision rather than being dropped in — there's a --2 modifier precedent at app.css:789 if a different column count is wanted.

3. "Investigate using metrics if applicable" — mostly not applicable, and there's a reason

Two things to know before reaching for Prometheus:

a. There are no job metrics today. The entire emitted set is http_requests_total and http_request_duration_seconds (crates/observability/src/middleware.rs:62-68) plus uptime_seconds (crates/observability/src/metrics.rs:69). Nothing counts exports or submissions, so metrics would have to be added first.

b. These cards are per-tenant, and /metrics must not carry tenant data. crates/observability/src/metrics.rs states the rule explicitly:

per-tenant resource-count gauges are intentionally NOT exported here. The /metrics endpoint is public (unauthenticated, for Prometheus scraping), and tenant is never a metric label — exporting per-tenant counts would leak cross-tenant data to any anonymous scraper.

The dashboard is tenant-scoped (dashboard::snapshot(window, &tenant.id), crates/ui/src/lib.rs:1294), so per-tenant job counts must not be sourced from /metrics. The established pattern for exactly this situation is the DashboardProvider / DashboardSnapshot path, which is tenant-aware and served through the authenticated console.

Process-wide job metrics (total jobs run, durations, failure counts, with no tenant label) would still be a reasonable separate addition for operators scraping Prometheus — just not the source for these cards.

4. The data already exists — this is plumbing, not new persistence

Both counts are already on the storage traits, tenant-scoped:

  • count_active_exports(&self, tenant)crates/persistence/src/core/bulk_export.rs:995, "counts active (accepted or in_progress) jobs for a tenant"
  • count_active_submissions(&self, tenant)crates/persistence/src/core/bulk_submit_worker.rs:302

So the work is: extend DashboardSnapshot (crates/observability/src/dashboard.rs:136-147, which has no job fields today) and StorageDashboardProvider (crates/rest/src/dashboard.rs:180-260) to carry these, then render them.

Two gaps to handle:

  • Backend coverage is uneven. count_active_submissions is implemented for sqlite, postgres, mongodb, and s3; count_active_exports only for sqlite and postgres. The cards need a graceful "unavailable" state rather than showing zero or a fabricated number where the backend can't answer.
  • "running" vs "queued". The card renders two figures (card-export-jobs-sub = running ({ $queued } queued), locales/en/main.ftl:140-141), but count_active_exports returns a single count covering both accepted and in_progress. Either split the query or change the copy — don't invent the breakdown.

5. "Investigate if Uptime is connected" — it is not

uptime_percent: "99.98" is hardcoded on the same line as the export placeholders (lib.rs:1375). A real uptime_seconds gauge does exist (crates/observability/src/uptime.rs, exported at metrics.rs:69), but the card claims an availability percentage over 30 days, which the in-process gauge cannot produce.

Unlike the job counts, uptime is process-wide, so /metrics is a legitimate source for it. This is already tracked separately in #540 — coordinate rather than fixing it twice here.

Acceptance criteria

  • Export jobs reflects real, tenant-scoped job state — no hardcoded values.
  • An Import jobs card exists, is hooked up, and links to /ui/bulk-import.
  • The stat grid lays out correctly with the added card, at desktop and the max-width: 1081px breakpoint.
  • Backends that cannot report a count render an explicit unavailable state, not a zero.
  • The "running / queued" split is either backed by real data or the copy is corrected.
  • No per-tenant data is added to /metrics.
  • A recorded decision on whether process-wide export/import metrics should be added for Prometheus separately.
  • Uptime handled in coordination with UI Home Page: wire the Uptime stat to Prometheus metrics (implement the metric if missing) #540, not duplicated.
  • New strings in locales/{en,es,de}/main.ftl.
  • e2e coverage in crates/ui/e2e/tests/dashboard.spec.ts, which today asserts only that the stat cards render.

Pointers

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions