TenantAtlas/specs/123-operations-auto-refresh/research.md
2026-03-08 11:34:09 +01:00

4.1 KiB
Raw Blame History

Research — Operations Auto-Refresh Pass

Decision: Reuse the shared run-detail polling helper for the tenantless operation run viewer

Rationale

  • The canonical operation detail surface already centralizes conditional polling in App\Support\OpsUx\RunDetailPolling.
  • OperationRunResource::infolist() already applies the established safeguards: stop polling when the browser tab is hidden and when Filament action modals are mounted.
  • TenantlessOperationRunViewer already delegates its infolist rendering to OperationRunResource, so the least-risk implementation path is to keep the tenantless page aligned with that shared detail-view contract instead of introducing a second polling policy.
  • Existing tests already cover the helpers active-versus-terminal behavior, which reduces the amount of new logic that needs fresh regression coverage.

Alternatives considered

  • Hard-code a new fixed 10s interval inside TenantlessOperationRunViewer — rejected because it would fork the run-detail behavior from the canonical operation detail pattern and risk drifting from the shared hidden-tab and modal-open guards.
  • Duplicate the RunDetailPolling logic inside the page class — rejected because it would create a second source of truth for active run polling.

Decision: Treat review pack queued and generating as the only active card states

Rationale

  • ReviewPackStatus defines a card-specific lifecycle: queued, generating, ready, failed, expired.
  • The widget view already renders queued and generating as the same in-progress state and renders ready, failed, and expired as terminal states.
  • ReviewPackService creates new records in queued, and GenerateReviewPackJob advances them into generating before landing in ready or failed.
  • Using the review-pack lifecycle directly avoids over-polling when unrelated tenant operation runs are active.

Alternatives considered

  • Drive the card from tenant-wide ActiveRuns::existForTenant() — rejected because this would keep the card polling for unrelated operations even when review-pack generation is not active.
  • Poll whenever any review pack exists — rejected because terminal states must remain stable and stop refreshing.

Decision: Attach review-pack polling at the widget root using the existing simple-widget Blade pattern

Rationale

  • TenantReviewPackCard is a plain Filament Widget, not a table or stats widget.
  • The closest established pattern is NeedsAttention, which computes a pollingInterval in PHP and conditionally emits wire:poll.{interval} on the root Blade element.
  • A root-level wire:poll.10s keeps the implementation small, readable, and consistent with the other lightweight dashboard widgets in the product.

Alternatives considered

  • Introduce a new shared global polling framework — rejected because the spec explicitly excludes a broader polling rewrite.
  • Move review-pack polling into JavaScript or browser events — rejected because the product already relies on Livewire/Filament polling for similar surfaces and the requested scope is intentionally small.

Decision: Extend existing helper and widget tests instead of inventing new verification infrastructure

Rationale

  • tests/Feature/OpsUx/RunDetailPollingStopsOnTerminalTest.php already verifies the canonical helper stops polling on terminal operation states and remains active for queued/running runs.
  • tests/Feature/ReviewPack/ReviewPackWidgetTest.php already covers the widgets empty, active, and terminal render states and is the most direct place to add polling assertions.
  • tests/Feature/Operations/TenantlessOperationRunViewerTest.php already covers tenantless access semantics and is the right page-level companion if markup-level assertions are needed.

Alternatives considered

  • Add a brand-new standalone polling test suite — rejected because the affected behavior already belongs to well-scoped existing helper and widget tests.
  • Rely on manual QA only — rejected because the spec requires automated coverage for active-versus-terminal polling behavior.