Skip to content

perf: coalesce polling snapshots - #343

Merged
mira-2026 merged 4 commits into
mainfrom
perf/server-polling-coalescing
Jul 28, 2026
Merged

perf: coalesce polling snapshots#343
mira-2026 merged 4 commits into
mainfrom
perf/server-polling-coalescing

Conversation

@mira-2026

@mira-2026 mira-2026 commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • add a fixed-key single-flight TTL/stale-while-revalidate snapshot layer for expensive polling reads
  • share Docker, GitHub PR, production checkout, preview, metrics, OpenClaw agent, and cron sampling across callers
  • invalidate affected snapshots after mutations while keeping action validation and sensitive reads fresh
  • add private ETag revalidation for the large Docker and pull-request payloads
  • expose snapshot and child-process telemetry through system metrics
  • centralize frontend refresh tiers and gate polling/reconnect work on visibility and online state
  • add bounded exponential WebSocket reconnect backoff with jitter and coalesce sessions.list refreshes

Safety

  • snapshots use fixed process-local keys only
  • stale data has a hard age boundary
  • invalidation detaches older in-flight producers so they cannot repopulate current state
  • Docker actions, PR mutations, auth checks, container details, and logs still use fresh reads
  • cache validators remain private and vary by cookie/authorization

Documentation

Docs: not needed — this changes internal polling, caching, and reconnect behavior without changing user-facing or operator contracts.

Verification

  • bun run format:check
  • bun run lint
  • bun run build
  • bun run test — frontend 485 passed; backend 601 passed
  • bun run test:frontend:coverage — 94.59% (required 85%)
  • bun run test:backend:coverage — 90.26% (required 85%)

@mira-2026
mira-2026 requested a review from rajohan as a code owner July 28, 2026 03:30
@mira-2026 mira-2026 added priority: medium Normal-priority planned work status: needs-review Ready for human or agent review type: performance Performance, resource usage, or responsiveness work area: backend Backend API, server routes, services, and integrations area: frontend Frontend UI, client state, routing, and browser behavior area: docker Docker views, stack controls, updater, or container actions area: openclaw OpenClaw gateway/API integration and runtime behavior labels Jul 28, 2026
@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@mira-2026, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 20 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 7621c1e6-ad9b-4347-a543-55bf803b6fd9

📥 Commits

Reviewing files that changed from the base of the PR and between a0364c4 and d3e6e10.

📒 Files selected for processing (2)
  • backend/src/services/openClawCronSnapshot.ts
  • backend/test/openClawCronSnapshot.test.ts
📝 Walkthrough

Walkthrough

The PR adds backend coalesced snapshots, cache invalidation, ETag responses, and telemetry, while centralizing frontend polling intervals and browser-aware WebSocket refresh behavior. Tests cover snapshot semantics, conditional HTTP responses, metrics, Docker caching, and socket reconnection.

Changes

Backend caching and telemetry

Layer / File(s) Summary
Snapshot, HTTP, and process primitives
backend/src/http.ts, backend/src/lib/coalescedSnapshot.ts, backend/src/lib/processes.ts, backend/test/coalescedSnapshot.test.ts, backend/test/httpCaching.test.ts
Adds reusable coalesced snapshots, SHA-256 JSON ETags, conditional 304 responses, child-process lifecycle metrics, and tests for snapshot and validator behavior.
Shared service snapshot sources
backend/src/services/agents.ts, backend/src/services/openClawCronSnapshot.ts, backend/src/services/taskAutomation.ts
Caches Gateway session and cron-list reads and centralizes cron normalization and invalidation.
Route snapshot and mutation integration
backend/src/routes/agentRoutes.ts, backend/src/routes/cronRoutes.ts, backend/src/routes/taskRoutes.ts, backend/src/routes/dockerRoutes.ts, backend/src/routes/pullRequestRoutes.ts
Routes reads through snapshots, adds Docker conditional responses, and invalidates cached data after mutations.
Backend metrics and route validation
backend/src/routes/metricsRoutes.ts, backend/test/routeAndServiceBehavior.test.ts, backend/test/setup.ts
Exposes snapshot and process telemetry, validates Docker failure and ETag behavior, and resets snapshot state between tests.

Frontend refresh and socket coordination

Layer / File(s) Summary
Central refresh policy and hook adoption
src/lib/refreshPolicy.ts, src/lib/queryClient.ts, src/hooks/*, src/components/features/chat/useChatHistory.ts, src/hooks/useMetrics.ts
Centralizes refresh tiers and browser polling checks, replacing hard-coded polling intervals and extending metrics response types.
Socket session refresh and reconnect control
src/lib/socket/socketClient.ts, src/hooks/useOpenClawSocket.ts, src/test/frontendBehavior.test.tsx
Coalesces session refreshes, gates polling by browser availability, adds bounded jittered reconnect delays, and tests reconnect and visibility behavior.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

Suggested labels: type: tests

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately reflects the main change: coalesced polling snapshots.
Description check ✅ Passed The description covers the key template sections and includes summary, safety, documentation, and verification details.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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.

Comment thread src/hooks/useOpenClawSocket.ts Fixed
@codecov

codecov Bot commented Jul 28, 2026

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
backend/src/routes/cronRoutes.ts (1)

37-43: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicate cron-list normalization logic across three files — consolidate into openClawCronSnapshot.ts.

cronRoutes.ts, taskAutomation.ts, and taskRoutes.ts each independently re-implement the same "extract .jobs, else .items, else []" fallback against the payload returned by getOpenClawCronListSnapshot(). Since all three now consume the same shared snapshot, export a single normalizeOpenClawCronJobs(payload): CronJob[] helper from openClawCronSnapshot.ts and have each call site use it.

  • backend/src/routes/cronRoutes.ts#L37-L43: replace local normalizeJobs with the shared helper.
  • backend/src/services/taskAutomation.ts#L109-L114: replace local normalizedCronJobs with the shared helper.
  • backend/src/routes/taskRoutes.ts#L202-L220: replace the inline jobs/items fallback in fetchCronJobsById with the shared helper.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/src/routes/cronRoutes.ts` around lines 37 - 43, Duplicate cron-job
normalization exists across three call sites; consolidate it into one shared
helper. Export normalizeOpenClawCronJobs(payload): CronJob[] from
openClawCronSnapshot.ts, then replace cronRoutes.ts lines 37-43 local
normalizeJobs, taskAutomation.ts lines 109-114 local normalizedCronJobs, and
taskRoutes.ts lines 202-220 inline jobs/items fallback with calls to the shared
helper, preserving the existing jobs-then-items-then-empty-array behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@backend/src/lib/coalescedSnapshot.ts`:
- Around line 23-28: Update SnapshotEntry and the read() flow so
retryAfterMs/nextRetryAt is enforced even when entry.value is absent. Record the
last load error when `#startLoad`() fails, set nextRetryAt, and have subsequent
reads before that time reuse or propagate the recorded failure instead of
starting another load; retain normal loading after the backoff expires and
existing cached-value behavior.

In `@backend/src/routes/dockerRoutes.ts`:
- Around line 759-761: Update the updater job flows for /api/docker/updater/run
and /api/docker/updater/services/:serviceId/update to invalidate read snapshots
after completion. Add invalidateDockerReadSnapshots() in finally blocks
surrounding both job waits, or route both through shared completion handling,
while preserving existing success and error behavior.

---

Nitpick comments:
In `@backend/src/routes/cronRoutes.ts`:
- Around line 37-43: Duplicate cron-job normalization exists across three call
sites; consolidate it into one shared helper. Export
normalizeOpenClawCronJobs(payload): CronJob[] from openClawCronSnapshot.ts, then
replace cronRoutes.ts lines 37-43 local normalizeJobs, taskAutomation.ts lines
109-114 local normalizedCronJobs, and taskRoutes.ts lines 202-220 inline
jobs/items fallback with calls to the shared helper, preserving the existing
jobs-then-items-then-empty-array behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: b4690447-85e2-4253-b9cf-090880614a02

📥 Commits

Reviewing files that changed from the base of the PR and between 97ae255 and 5fbbba1.

📒 Files selected for processing (32)
  • backend/src/http.ts
  • backend/src/lib/coalescedSnapshot.ts
  • backend/src/lib/processes.ts
  • backend/src/routes/agentRoutes.ts
  • backend/src/routes/cronRoutes.ts
  • backend/src/routes/dockerRoutes.ts
  • backend/src/routes/metricsRoutes.ts
  • backend/src/routes/pullRequestRoutes.ts
  • backend/src/routes/taskRoutes.ts
  • backend/src/services/agents.ts
  • backend/src/services/openClawCronSnapshot.ts
  • backend/src/services/taskAutomation.ts
  • backend/test/coalescedSnapshot.test.ts
  • backend/test/httpCaching.test.ts
  • backend/test/routeAndServiceBehavior.test.ts
  • backend/test/setup.ts
  • src/components/features/chat/useChatHistory.ts
  • src/hooks/useAgents.ts
  • src/hooks/useBackups.ts
  • src/hooks/useCron.ts
  • src/hooks/useDelivery.ts
  • src/hooks/useDocker.ts
  • src/hooks/useHealth.ts
  • src/hooks/useJobExecutions.ts
  • src/hooks/useMetrics.ts
  • src/hooks/useOpenClawSocket.ts
  • src/hooks/useReports.ts
  • src/hooks/useScheduledJobs.ts
  • src/lib/queryClient.ts
  • src/lib/refreshPolicy.ts
  • src/lib/socket/socketClient.ts
  • src/test/frontendBehavior.test.tsx
📜 Review details
⏰ Context from checks skipped due to timeout. (3)
  • GitHub Check: backend-checks
  • GitHub Check: frontend-checks
  • GitHub Check: Analyze JavaScript and TypeScript
🔇 Additional comments (35)
backend/src/routes/dockerRoutes.ts (1)

2-3: LGTM!

Also applies to: 310-315, 376-394, 683-691, 736-757, 763-788, 832-832

backend/src/routes/metricsRoutes.ts (1)

7-16: LGTM!

Also applies to: 76-85, 346-364

backend/test/coalescedSnapshot.test.ts (1)

1-111: LGTM!

backend/test/httpCaching.test.ts (1)

1-39: LGTM!

backend/test/routeAndServiceBehavior.test.ts (1)

2833-2848: LGTM!

Also applies to: 3640-3643, 3656-3662

backend/test/setup.ts (1)

7-7: LGTM!

Also applies to: 49-49

src/lib/refreshPolicy.ts (1)

1-15: LGTM!

src/components/features/chat/useChatHistory.ts (1)

10-10: LGTM!

Also applies to: 24-24, 247-252

src/hooks/useAgents.ts (1)

3-3: LGTM!

Also applies to: 45-45, 67-67, 78-78

src/hooks/useCron.ts (1)

3-3: LGTM!

Also applies to: 44-44

src/hooks/useDocker.ts (1)

3-3: LGTM!

Also applies to: 210-211, 285-285, 301-301

src/hooks/useHealth.ts (1)

3-3: LGTM!

Also applies to: 39-39

src/hooks/useReports.ts (1)

3-3: LGTM!

Also applies to: 52-52

src/hooks/useMetrics.ts (1)

37-56: LGTM!

src/hooks/useBackups.ts (1)

3-3: LGTM!

Also applies to: 43-43, 56-56

src/hooks/useDelivery.ts (1)

4-4: LGTM!

Also applies to: 168-168, 290-292, 337-337

src/hooks/useJobExecutions.ts (1)

8-8: LGTM!

Also applies to: 84-84

src/hooks/useScheduledJobs.ts (1)

3-3: LGTM!

Also applies to: 122-125, 139-144

src/lib/queryClient.ts (1)

3-6: LGTM!

src/hooks/useOpenClawSocket.ts (1)

18-18: LGTM!

Also applies to: 59-59, 79-100, 121-123, 171-171, 247-265, 277-277, 292-292, 314-314

src/lib/socket/socketClient.ts (1)

3-3: LGTM!

Also applies to: 14-34, 89-90, 118-138, 214-224, 313-313, 328-329

src/test/frontendBehavior.test.tsx (1)

205-205: LGTM!

Also applies to: 1750-1812

backend/src/routes/pullRequestRoutes.ts (4)

1-2: LGTM!

Also applies to: 44-78, 80-95


109-113: LGTM!

Also applies to: 131-135, 146-150, 161-163, 174-184, 195-202


211-216: LGTM!

Also applies to: 250-256


265-265: LGTM!

Also applies to: 274-274

backend/src/http.ts (1)

1-2: LGTM!

Also applies to: 61-92

backend/src/lib/coalescedSnapshot.ts (1)

1-158: LGTM!

Also applies to: 199-238

backend/src/lib/processes.ts (1)

19-35: LGTM!

Also applies to: 80-80, 89-110

backend/src/services/agents.ts (1)

7-7: LGTM!

Also applies to: 409-409, 483-493

backend/src/services/openClawCronSnapshot.ts (1)

1-19: LGTM!

backend/src/services/taskAutomation.ts (1)

3-6: LGTM!

Also applies to: 182-182

backend/src/routes/agentRoutes.ts (2)

1-2: Import summary doesn't match code: json is still imported and used.

The line-range summary states the json import was removed, but line 1 still imports json from ../http.ts, and it's used throughout this file (agentError, missingConfig, and every route handler). The code should be treated as authoritative here.


27-44: LGTM!

Also applies to: 59-63, 105-105

backend/src/routes/cronRoutes.ts (1)

13-16: LGTM!

Also applies to: 52-59, 86-88, 100-104, 123-127, 161-167, 191-204

Comment thread backend/src/lib/coalescedSnapshot.ts
Comment thread backend/src/routes/dockerRoutes.ts

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e299b1d6b7

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread backend/src/routes/dockerRoutes.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@backend/src/services/openClawCronSnapshot.ts`:
- Around line 21-27: Update normalizeOpenClawCronJobs to validate the outer
payload and each cron entry before returning results: reject array payloads,
require jobs/items to be arrays of non-null objects, and treat an empty object
or missing/invalid list as an unavailable/error snapshot rather than a healthy
empty list. Preserve the generic return type only for validated entries and
update callers as needed to handle the rejected-payload outcome.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 133afc41-5a8f-4bc7-b0ab-0ade61381b57

📥 Commits

Reviewing files that changed from the base of the PR and between 5fbbba1 and a0364c4.

📒 Files selected for processing (9)
  • backend/src/lib/coalescedSnapshot.ts
  • backend/src/routes/cronRoutes.ts
  • backend/src/routes/dockerRoutes.ts
  • backend/src/routes/taskRoutes.ts
  • backend/src/services/openClawCronSnapshot.ts
  • backend/src/services/taskAutomation.ts
  • backend/test/coalescedSnapshot.test.ts
  • backend/test/routeAndServiceBehavior.test.ts
  • src/hooks/useOpenClawSocket.ts
🚧 Files skipped from review as they are similar to previous changes (7)
  • backend/src/routes/taskRoutes.ts
  • backend/test/coalescedSnapshot.test.ts
  • backend/src/routes/dockerRoutes.ts
  • src/hooks/useOpenClawSocket.ts
  • backend/test/routeAndServiceBehavior.test.ts
  • backend/src/routes/cronRoutes.ts
  • backend/src/lib/coalescedSnapshot.ts
📜 Review details
⏰ Context from checks skipped due to timeout. (3)
  • GitHub Check: Analyze JavaScript and TypeScript
  • GitHub Check: frontend-checks
  • GitHub Check: backend-checks
🔇 Additional comments (2)
backend/src/services/openClawCronSnapshot.ts (1)

1-9: LGTM!

Also applies to: 11-19, 29-32

backend/src/services/taskAutomation.ts (1)

6-9: LGTM!

Also applies to: 173-175

Comment thread backend/src/services/openClawCronSnapshot.ts
@mira-2026
mira-2026 merged commit 96f613d into main Jul 28, 2026
7 checks passed
@mira-2026
mira-2026 deleted the perf/server-polling-coalescing branch July 28, 2026 05:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: backend Backend API, server routes, services, and integrations area: docker Docker views, stack controls, updater, or container actions area: frontend Frontend UI, client state, routing, and browser behavior area: openclaw OpenClaw gateway/API integration and runtime behavior priority: medium Normal-priority planned work status: needs-review Ready for human or agent review type: performance Performance, resource usage, or responsiveness work

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants