Skip to content

Better observability to EMMA#2122

Merged
GelatoGenesis merged 3 commits intomainfrom
b-17736675453
Mar 16, 2026
Merged

Better observability to EMMA#2122
GelatoGenesis merged 3 commits intomainfrom
b-17736675453

Conversation

@GelatoGenesis
Copy link
Copy Markdown
Collaborator

@GelatoGenesis GelatoGenesis commented Mar 16, 2026

Summary by CodeRabbit

  • New Features

    • Retry button for failed token-pool snapshot attempts.
    • Copy-to-clipboard for snapshot fields.
    • Live, stage-based snapshot status with progress and timestamps.
    • Optional control to disable the Next button.
  • Improvements

    • Polling-driven refresh and explicit refresh handler for snapshot status.
    • Clearer failure notices, issue summaries, and refined UI state for multi-step workflows.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 16, 2026

📝 Walkthrough

Walkthrough

Adds richer download state and timing metadata, moves snapshot generation to a derived, polling-driven model, threads a refresh handler through snapshot table components, enriches per-row status UI with progress/stage/retry logic, and introduces a retry component that invokes a retry API endpoint.

Changes

Cohort / File(s) Summary
Type System & Types
components/allowlist-tool/allowlist-tool.types.ts
Added DistributionPlanTokenPoolDownloadStage enum and expanded DistributionPlanTokenPoolDownload with many state, progress, attempt/failure counts and timestamps.
CreateSnapshots core
components/distribution-plan-tool/create-snapshots/CreateSnapshots.tsx
Refactored snapshots to be derived from operations via CreateTokenPoolOperationParams parser; replaced downloaderStatus with download object; added loadTokenPoolDownloads() fetcher, dynamic polling cadence, and derived signals (active/unresolved/failed/allCompleted); added failure UI.
Table prop threading
components/distribution-plan-tool/create-snapshots/table/CreateSnapshotTable.tsx, components/distribution-plan-tool/create-snapshots/table/CreateSnapshotTableBody.tsx
Added and propagated new prop refreshDownloads: () => Promise<void> from table → body → rows.
Row rendering & UX
components/distribution-plan-tool/create-snapshots/table/CreateSnapshotTableRow.tsx
Rewrote row to render rich status: stage, progress, activity, issues, previous failures; added copy-to-clipboard per-field with 3s feedback; derives status from DistributionPlanTokenPoolDownload; accepts refreshDownloads prop.
Retry action
components/distribution-plan-tool/create-snapshots/table/CreateSnapshotTableRowRetry.tsx
New component that POSTs retry to /allowlists/{allowlistId}/token-pool-downloads/token-pool/{tokenPoolId}/retry, shows loader/toast, and calls refreshDownloads() on success.
Button tweak
components/distribution-plan-tool/common/DistributionPlanNextStepBtn.tsx
Added optional disableNextBtn?: boolean prop and wired isDisabled to it (default false).
Minor formatting / comments
components/allowlist-tool/allowlist-tool.types.ts
Small formatting change for an extends clause and an added eslint-disable comment (no signature change).

Sequence Diagram

sequenceDiagram
    participant CS as CreateSnapshots
    participant Row as CreateSnapshotTableRow
    participant API as Distribution API
    participant Toast as Toast Service

    CS->>API: loadTokenPoolDownloads(allowlistId)
    API-->>CS: downloads (status, stage, progress, timestamps)
    CS->>Row: pass snapshot + download + refreshDownloads
    Row->>Row: render status, stage, progress, issues

    alt download.retryable
        Row->>API: POST /token-pool-downloads/token-pool/{tokenPoolId}/retry
        API-->>Toast: success
        Toast-->>Row: show "Snapshot retry started"
        Row->>CS: call refreshDownloads()
        CS->>API: reload downloads
    else active/pending
        CS->>CS: continue polling (dynamic delay)
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

  • Multi subscriptions #1612: Overlapping edits to distribution-plan-tool create-snapshots UI and related row/table components; changes to download-driven status types are directly relevant.

Suggested reviewers

  • simo6529
  • ragnep

Poem

🐰 I nibble logs and count each stage,
Polling beats that pace the page,
Retry button gives a hopeful hop,
Badges shine and spinners stop,
Hooray — snapshots hum along, hip-hop! 🎉

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Better observability to EMMA' is vague and generic, using non-descriptive terms that don't convey meaningful information about the specific changes in the changeset. Make the title more specific and descriptive. Consider referencing the key technical changes, such as 'Add download status tracking and retry mechanism to token pool snapshots' or 'Enhance token pool download observability with detailed status stages and progress tracking'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch b-17736675453
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@components/distribution-plan-tool/create-snapshots/CreateSnapshots.tsx`:
- Around line 124-159: Add a hasRan flag to each snapshot in the snapshots map
(derive it from tokenPoolDownload.hasRan or compute from
tokenPoolDownload.status) and then change the activeSnapshots selection so it
does NOT treat every download === null snapshot as active; instead only include
snapshots where download === null (no job yet) OR where a download exists and it
hasRan === true and the download is not stalled/PENDING/CLAIMED; exclude
snapshots whose download exists but is stale/hasn't run. Update the
CreateSnapshots snapshot construction (the snapshots constant, tokenPoolDownload
variable) and the activeSnapshots filter to use the new hasRan property.
- Around line 271-279: The Run analysis button is hidden because
showRunAnalysisBtn is gated by allSnapshotsCompleted; change the visibility to
depend only on haveUnRunOperations so users can start jobs when there are un-run
operations. In the DistributionPlanNextStepBtn props, set
showRunAnalysisBtn={haveUnRunOperations} (keep
disableNextBtn={!allSnapshotsCompleted} so Next remains disabled until snapshots
complete) and keep existing
setStep/DistributionPlanToolStep.CREATE_CUSTOM_SNAPSHOT behavior unchanged.

In
`@components/distribution-plan-tool/create-snapshots/table/CreateSnapshotTableRow.tsx`:
- Around line 83-117: The switch over download.stage in CreateSnapshotTableRow
currently has no default, so unknown/new EMMA stage values render nothing;
update the switch (the code handling download.stage /
DistributionPlanTokenPoolDownloadStage) to include a default/fallback case that
returns a clear label (for example "Unknown stage" or "Unknown stage:
{download.stage}") so the UI always shows a meaningful string for unrecognized
stages; ensure you add the default case at the end of the switch (or a final
return after the switch) so it covers any future enum values.

In
`@components/distribution-plan-tool/create-snapshots/table/CreateSnapshotTableRowRetry.tsx`:
- Around line 38-46: The Retry button in CreateSnapshotTableRowRetry (the button
that calls onRetry and uses the loading prop) is icon-only and lacks an
accessible name; add an aria-label (e.g., aria-label="Retry snapshot") to the
button and include aria-busy={loading} so assistive tech knows when the retry is
in flight; keep existing title if desired but ensure the button element with
onRetry and loading props includes both aria-label and aria-busy attributes.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ad029cdf-94cb-4ded-9a5b-9c1d7b37487f

📥 Commits

Reviewing files that changed from the base of the PR and between 155142a and b1e55f3.

📒 Files selected for processing (7)
  • components/allowlist-tool/allowlist-tool.types.ts
  • components/distribution-plan-tool/common/DistributionPlanNextStepBtn.tsx
  • components/distribution-plan-tool/create-snapshots/CreateSnapshots.tsx
  • components/distribution-plan-tool/create-snapshots/table/CreateSnapshotTable.tsx
  • components/distribution-plan-tool/create-snapshots/table/CreateSnapshotTableBody.tsx
  • components/distribution-plan-tool/create-snapshots/table/CreateSnapshotTableRow.tsx
  • components/distribution-plan-tool/create-snapshots/table/CreateSnapshotTableRowRetry.tsx

Signed-off-by: GelatoGenesis <tarmokalling@gmail.com>
Signed-off-by: GelatoGenesis <tarmokalling@gmail.com>
Signed-off-by: GelatoGenesis <tarmokalling@gmail.com>
@sonarqubecloud
Copy link
Copy Markdown

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (3)
components/distribution-plan-tool/create-snapshots/table/CreateSnapshotTableRow.tsx (1)

84-118: ⚠️ Potential issue | 🟡 Minor

Add a default case to handle unknown download stages.

The switch statement doesn't have a default case. If the API returns a new stage value not yet in the enum, the function returns undefined, causing the UI to display nothing for the stage. This was flagged in a previous review and remains unaddressed.

🛡️ Proposed fix
     case DistributionPlanTokenPoolDownloadStage.FAILED:
       return "Snapshot failed";
+    default:
+      return typeof download.stage === "string"
+        ? `Unknown stage (${download.stage})`
+        : "Processing";
   }
 };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@components/distribution-plan-tool/create-snapshots/table/CreateSnapshotTableRow.tsx`
around lines 84 - 118, The switch over download.stage in CreateSnapshotTableRow
(in CreateSnapshotTableRow.tsx) lacks a default branch, so add a default case to
the switch(download.stage) that returns a clear fallback string (e.g., "Unknown
stage" or `Unknown stage: ${download.stage}`) and optionally call a logger/warn
(e.g., console.warn or your app logger) with the unexpected value so the UI
never renders undefined and new/unknown enum values are visible for debugging;
update the default case rather than changing the existing specific cases.
components/distribution-plan-tool/create-snapshots/CreateSnapshots.tsx (2)

190-197: ⚠️ Potential issue | 🟠 Major

Fast-polling triggers for snapshots that haven't been run yet.

The activeSnapshots filter includes snapshots where !snapshot.download, which encompasses jobs that haven't been triggered at all (before "Run analysis" is clicked). This causes unnecessary 2-second polling before any work has started and for stalled jobs. Consider excluding snapshots that haven't run or are stale.

⚙️ Proposed fix
   const activeSnapshots = snapshots.filter((snapshot) => {
-    const rawStatus = snapshot.download?.rawStatus ?? null;
-    return (
-      !snapshot.download ||
-      rawStatus === DistributionPlanTokenPoolDownloadStatus.PENDING ||
-      rawStatus === DistributionPlanTokenPoolDownloadStatus.CLAIMED
-    );
+    // Only poll for snapshots that have a download in progress (not stale)
+    if (!snapshot.download) {
+      return false;
+    }
+    if (snapshot.download.stale) {
+      return false;
+    }
+    return [
+      DistributionPlanTokenPoolDownloadStatus.PENDING,
+      DistributionPlanTokenPoolDownloadStatus.CLAIMED,
+    ].includes(snapshot.download.rawStatus);
   });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/distribution-plan-tool/create-snapshots/CreateSnapshots.tsx`
around lines 190 - 197, The filter for activeSnapshots currently includes
!snapshot.download which causes polling of snapshots that were never started;
update the activeSnapshots filter so it only considers snapshots with a download
and with rawStatus === DistributionPlanTokenPoolDownloadStatus.PENDING ||
rawStatus === DistributionPlanTokenPoolDownloadStatus.CLAIMED (i.e., remove the
!snapshot.download branch), and optionally add a staleness guard using
snapshot.download?.createdAt or snapshot.download?.updatedAt compared against a
STALE_THRESHOLD_MS constant to skip downloads older than the threshold; update
the logic around the activeSnapshots constant to reference snapshot.download
before checking rawStatus.

270-279: ⚠️ Potential issue | 🔴 Critical

User gets stuck when there are un-run snapshot operations.

The logic gates showRunAnalysisBtn on allSnapshotsCompleted && haveUnRunOperations. However, when operations haven't run yet, allSnapshotsCompleted is false (no completed downloads), so the "Run analysis" button is hidden. Meanwhile, the "Next" button is shown but disabled. The user cannot proceed.

🐛 Proposed fix
         <DistributionPlanNextStepBtn
-          showRunAnalysisBtn={allSnapshotsCompleted && haveUnRunOperations}
+          showRunAnalysisBtn={haveUnRunOperations}
           onNextStep={() =>
             setStep(DistributionPlanToolStep.CREATE_CUSTOM_SNAPSHOT)
           }
           loading={false}
-          showNextBtn={haveSnapshots}
+          showNextBtn={haveSnapshots && !haveUnRunOperations}
           showSkipBtn={false}
           disableNextBtn={!allSnapshotsCompleted}
         />
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/distribution-plan-tool/create-snapshots/CreateSnapshots.tsx`
around lines 270 - 279, The "Run analysis" button is hidden because
showRunAnalysisBtn is gated by allSnapshotsCompleted; change showRunAnalysisBtn
to depend only on haveUnRunOperations (showRunAnalysisBtn={haveUnRunOperations})
so the button is visible whenever there are un-run snapshot operations, and
adjust the Next button disable logic to prevent the user progressing while
un-run ops exist by setting disableNextBtn to include haveUnRunOperations (for
example disableNextBtn={haveUnRunOperations || !allSnapshotsCompleted}); update
the props on the DistributionPlanNextStepBtn component accordingly.
🧹 Nitpick comments (1)
components/distribution-plan-tool/create-snapshots/table/CreateSnapshotTableRowRetry.tsx (1)

22-37: Consider handling API failure with user feedback.

When success is false, the user receives no indication that the retry failed. Consider adding an error toast to inform users.

💡 Proposed fix
     if (success) {
       setToasts({
         messages: ["Snapshot retry started"],
         type: "success",
       });
       await refreshDownloads();
+    } else {
+      setToasts({
+        messages: ["Snapshot retry failed"],
+        type: "error",
+      });
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@components/distribution-plan-tool/create-snapshots/table/CreateSnapshotTableRowRetry.tsx`
around lines 22 - 37, The onRetry handler currently only shows success toasts
and leaves users uninformed on failure; update onRetry (the async function that
calls distributionPlanApiPost) to handle both non-success responses and thrown
errors by showing an error toast via setToasts (e.g., messages: ["Snapshot retry
failed"] or include error.message), and ensure setLoading(false) runs in all
cases (use try/catch/finally around the distributionPlanApiPost call and await
refreshDownloads only on success).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@components/distribution-plan-tool/create-snapshots/CreateSnapshots.tsx`:
- Around line 190-197: The filter for activeSnapshots currently includes
!snapshot.download which causes polling of snapshots that were never started;
update the activeSnapshots filter so it only considers snapshots with a download
and with rawStatus === DistributionPlanTokenPoolDownloadStatus.PENDING ||
rawStatus === DistributionPlanTokenPoolDownloadStatus.CLAIMED (i.e., remove the
!snapshot.download branch), and optionally add a staleness guard using
snapshot.download?.createdAt or snapshot.download?.updatedAt compared against a
STALE_THRESHOLD_MS constant to skip downloads older than the threshold; update
the logic around the activeSnapshots constant to reference snapshot.download
before checking rawStatus.
- Around line 270-279: The "Run analysis" button is hidden because
showRunAnalysisBtn is gated by allSnapshotsCompleted; change showRunAnalysisBtn
to depend only on haveUnRunOperations (showRunAnalysisBtn={haveUnRunOperations})
so the button is visible whenever there are un-run snapshot operations, and
adjust the Next button disable logic to prevent the user progressing while
un-run ops exist by setting disableNextBtn to include haveUnRunOperations (for
example disableNextBtn={haveUnRunOperations || !allSnapshotsCompleted}); update
the props on the DistributionPlanNextStepBtn component accordingly.

In
`@components/distribution-plan-tool/create-snapshots/table/CreateSnapshotTableRow.tsx`:
- Around line 84-118: The switch over download.stage in CreateSnapshotTableRow
(in CreateSnapshotTableRow.tsx) lacks a default branch, so add a default case to
the switch(download.stage) that returns a clear fallback string (e.g., "Unknown
stage" or `Unknown stage: ${download.stage}`) and optionally call a logger/warn
(e.g., console.warn or your app logger) with the unexpected value so the UI
never renders undefined and new/unknown enum values are visible for debugging;
update the default case rather than changing the existing specific cases.

---

Nitpick comments:
In
`@components/distribution-plan-tool/create-snapshots/table/CreateSnapshotTableRowRetry.tsx`:
- Around line 22-37: The onRetry handler currently only shows success toasts and
leaves users uninformed on failure; update onRetry (the async function that
calls distributionPlanApiPost) to handle both non-success responses and thrown
errors by showing an error toast via setToasts (e.g., messages: ["Snapshot retry
failed"] or include error.message), and ensure setLoading(false) runs in all
cases (use try/catch/finally around the distributionPlanApiPost call and await
refreshDownloads only on success).

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a44a741f-2089-4fd5-9be6-ef4b8e22b132

📥 Commits

Reviewing files that changed from the base of the PR and between b1e55f3 and 31ad6e7.

📒 Files selected for processing (7)
  • components/allowlist-tool/allowlist-tool.types.ts
  • components/distribution-plan-tool/common/DistributionPlanNextStepBtn.tsx
  • components/distribution-plan-tool/create-snapshots/CreateSnapshots.tsx
  • components/distribution-plan-tool/create-snapshots/table/CreateSnapshotTable.tsx
  • components/distribution-plan-tool/create-snapshots/table/CreateSnapshotTableBody.tsx
  • components/distribution-plan-tool/create-snapshots/table/CreateSnapshotTableRow.tsx
  • components/distribution-plan-tool/create-snapshots/table/CreateSnapshotTableRowRetry.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • components/distribution-plan-tool/create-snapshots/table/CreateSnapshotTableBody.tsx

@GelatoGenesis GelatoGenesis merged commit 3c91e4f into main Mar 16, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants