show the pulsing 'anchoring' pill on fresh decisions, not the terminal 'not anchored' marker#21
Conversation
…e timeline never sits on '— not anchored' for fresh rows: until this commit, hitting evaluate caused the new decision to render in the timeline immediately with the terminal '— not anchored' marker because the server returns the decision before the 0g storage upload settles (the upload is fire-and-forget per zeroGStore.scheduleAnchor for the same '50ms hot path' reason that policy creation uses), so users sat staring at a row that looked like it had failed when in reality the anchor would land 5-30s later — they had no way to know the difference without manually refreshing or watching the lime '0G | 0xroot...' pill appear; web/src/lib/timeline.ts now mirrors the policies.ts treatment with a module-level pendingDecisionAnchors Map<id, startTime> and a single shared poll loop (one window.setInterval shared across all in-flight ids, vs one timer per id) that fetches /timeline every 2s for up to 30s per id; markDecisionPending(id) is exported so the evaluate flow can register a fresh decision the instant POST /evaluate returns, the next loadTimeline render reads from the map and emits anchorPendingPillHtml() (pulsing lime dot + italic 'anchoring' text + breathing opacity) instead of the terminal anchorPillHtml(undefined) for any id still in flight; loadTimeline drains the map on every render — for each row whose response now carries a non-empty rootHash the id is pulled from the map and the pill flips to the green link without a visual jolt; the shared timer self-stops when the map drains (size === 0) so we don't burn an interval forever after all anchors land, and the per-id timeout (30s) kicks any id that fails to anchor (network blip, indexer down, wallet drained) out of the map so the pill drops to the terminal '— not anchored' state rather than pulsing forever; web/src/lib/evaluate.ts imports markDecisionPending and calls it from submitEvaluateForm right after the post returns, gated on the response carrying an id and lacking a rootHash so existing rows with already-landed anchors don't re-enter the pending state on a retry; the call happens before await loadTimeline() so the very first render of the new row already shows the pending pill rather than flashing 'not anchored' for one frame before the next poll catches up
|
Warning Rate limit exceeded
To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Review rate limit: 0/1 reviews remaining, refill in 28 minutes and 49 seconds.Comment |
Deploying chainshield with
|
| Latest commit: |
9d23105
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://e1abb497.chainshield.pages.dev |
| Branch Preview URL: | https://feat-decision-anchor-pending.chainshield.pages.dev |
Summary
The timeline already has a great pulsing pill (
anchorPendingPillHtml) for in-flight 0G uploads, but it was only wired into the policies flow. Fresh decisions submitted via Evaluate were rendered with the terminal "— not anchored" marker immediately, even though the server's fire-and-forget anchor was still uploading. Users had to manually refresh to see the green link land 5-30s later.This PR extends the same pattern from
policies.tstotimeline.ts:pendingDecisionAnchors: Map<id, startTime>tracks decisions whose anchor is still uploading on the server.markDecisionPending(id)is called fromsubmitEvaluateFormright afterPOST /evaluatereturns, gated on the response lacking a rootHash so existing anchored rows don't re-enter pending on a retry.setIntervalpollsGET /timelineevery 2s and re-renders. When a row's response carries a rootHash, the id is drained from the map and the pill flips to the lime "0G | 0xroot..." link without a visual jolt.Test plan
bun run typecheck(server + Astro) — 0 errors / warnings / hintsbun test— 101 passbun run build:web— cleanNeed help on this PR? Tag
@codesmithwith what you need.