Skip to content

feat(admin): builder pool free/used capacity - #2901

Merged
riderx merged 6 commits into
mainfrom
feat/admin-builder-capacity
Aug 7, 2026
Merged

feat(admin): builder pool free/used capacity#2901
riderx merged 6 commits into
mainfrom
feat/admin-builder-capacity

Conversation

@riderx

@riderx riderx commented Aug 6, 2026

Copy link
Copy Markdown
Member

Summary (AI generated)

  • Add builder_capacity_events (+/− worker pool size over time) and persist build_requests.started_at / completed_at
  • New admin_stats category builder_capacity: live available/running from builder runners, hourly free/used reconstructed from capacity events + build intervals
  • Admin Builder tab: live cards + hourly free/used/workers chart

Motivation (AI generated)

Need to see current free vs busy builders and historical hourly utilization without cron snapshots — event log of worker count plus existing build start/end is enough to reconstruct the series.

Business Impact (AI generated)

Faster ops visibility into builder saturation and queue pressure, so we can scale MacInCloud runners before customers wait.

Test Plan (AI generated)

  • bun test:unit includes tests/builder-capacity.unit.test.ts and admin_stats schema acceptance
  • bun run supabase:db:reset applies 20260806202503_builder_capacity_events.sql
  • Open /admin/dashboard/builder/ as platform admin — see Available / Running / Online / Waiting / Offline cards
  • Confirm hourly chart populates after capacity sync + builds with start/end
  • With BUILDER_URL unreachable, cards show builder unreachable and chart still uses stored events/logs

Generated with AI

Made with Cursor


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

Review in cubic

Summary by CodeRabbit

  • New Features

    • Added builder-capacity analytics to the admin dashboard, including live worker availability and hourly workers, used, and free capacity.
    • Added capacity reporting for build workers and historical capacity tracking.
    • Added hourly date granularity for chart labels.
    • Build activity now includes start and completion timestamps for improved reporting.
  • Tests

    • Added coverage for capacity reconstruction, hourly metrics, and admin metric validation.

Track worker pool size as +/- capacity events and persist build
start/end intervals so the admin Builder tab can show live
available/running workers and reconstruct hourly free vs used.

Co-authored-by: Cursor <cursoragent@cursor.com>
@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 23 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: ASSERTIVE

Plan: Pro

Run ID: 91e77924-3236-4f8f-bd38-f3d60cfb3b57

📥 Commits

Reviewing files that changed from the base of the PR and between e381fed and a9f2b35.

📒 Files selected for processing (11)
  • cli/src/build/prescan/overrides.ts
  • src/components/admin/AdminMultiLineChart.vue
  • src/pages/admin/dashboard/builder.vue
  • src/types/supabase.types.ts
  • supabase/functions/_backend/public/build/capacity.ts
  • supabase/functions/_backend/public/build/start.ts
  • supabase/functions/_backend/utils/builder_capacity.ts
  • supabase/functions/_backend/utils/supabase.types.ts
  • supabase/migrations/20260807121500_builder_capacity_events.sql
  • tests/audit-logs.test.ts
  • tests/builder-capacity.unit.test.ts
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

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

@cursor

cursor Bot commented Aug 6, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_1f9dfe4a-93eb-4221-8487-7bcf9c31c638)

@cubic-dev-ai cubic-dev-ai 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.

All reported issues were addressed across 13 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread supabase/functions/_backend/utils/builder_capacity.ts
Comment thread supabase/functions/_backend/utils/builder_capacity.ts Outdated
Comment thread supabase/functions/_backend/utils/builder_capacity.ts Outdated
Comment thread supabase/functions/_backend/utils/builder_capacity.ts Outdated
Comment thread supabase/migrations/20260807121500_builder_capacity_events.sql
Comment thread src/pages/admin/dashboard/builder.vue Outdated
Comment thread supabase/functions/_backend/triggers/cron_reconcile_build_status.ts
Comment thread supabase/functions/_backend/utils/builder_capacity.ts Outdated
Comment thread src/components/admin/AdminMultiLineChart.vue
Comment thread supabase/functions/_backend/utils/builder_capacity.ts Outdated
Seed the current pool size and let the builder worker POST
worker +/- events to /build/capacity instead of recording on admin reads.

Co-authored-by: Cursor <cursoragent@cursor.com>
@riderx

riderx commented Aug 7, 2026

Copy link
Copy Markdown
Member Author

Follow-up (AI generated)

  • Migration now seeds 3 workers (source=seed)
  • Capacity events are no longer written from admin page loads
  • New POST /build/capacity (auth: BUILDER_API_KEY) for the builder worker to report pool size on runner create/delete

Companion builder PR incoming.

@cursor

cursor Bot commented Aug 7, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_2ef0954e-2ae7-4152-bbbc-f5fa086be3c1)

@riderx

riderx commented Aug 7, 2026

Copy link
Copy Markdown
Member Author

Builder companion PR: https://github.com/Cap-go/capgo_builder/pull/167/

@coderabbitai coderabbitai Bot added the codex label Aug 7, 2026
@codspeed-hq

codspeed-hq Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 43 untouched benchmarks
⏩ 2 skipped benchmarks1


Comparing feat/admin-builder-capacity (a9f2b35) with main (d76ef26)

Open in CodSpeed

Footnotes

  1. 2 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

Use builder-reported run starts only, reconstruct hourly usage in one
sweep clipped to the selected range, record capacity events atomically,
and harden the admin UI for unreachable/zero-worker states.

Co-authored-by: Cursor <cursoragent@cursor.com>
@cursor

cursor Bot commented Aug 7, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_72105748-da01-4144-885a-4c4d21c92ce1)

@riderx

riderx commented Aug 7, 2026

Copy link
Copy Markdown
Member Author

Review fixes (AI generated)

Addressed in 0cf05f93c:

  • P1 used includes queue timestarted_at only from builder-reported run start; start.ts no longer writes wall-clock; intervals exclude waiting_runner
  • P2 admin-sampled history — already handled by POST /build/capacity from the builder (companion PR)
  • P2 O(hours×runs) — single sweep-line reconstruction
  • P2 range clip — first/last hour bins clipped to selected range
  • P2 invalid intervalscompleted_at >= started_at check on build_requests
  • P2 zero workers chart — show chart when capacity events/runs exist even if values are 0
  • P2 unreachable shows 0 — live cards show + unreachable subtitle
  • P2 PageLoader blocked — capacity loads independently (void loadCapacity())
  • P2 started_at semantics — submission no longer sets started_at
  • P2 concurrent delta — advisory lock around capacity event insert
  • P3 hour labels — short formatLocalTime labels
  • P3 waiting_runner in used — fallback counts only running

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 10

🤖 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 `@src/pages/admin/dashboard/builder.vue`:
- Around line 271-283: Update the loadCapacity flow to call
adminStore.fetchStats('builder_capacity', true), then create a managed refresh
interval that invokes loadCapacity while the dashboard is open. Store the
interval handle and clear it during the component’s unmount lifecycle,
preserving the existing loading and error handling.

In `@supabase/functions/_backend/public/build/capacity.ts`:
- Around line 1-21: Import MiddlewareKeyVariables from ../../utils/hono.ts and
type both assertBuilderApiKey and reportBuilderCapacity with
Context<MiddlewareKeyVariables>. Preserve their existing behavior while ensuring
requestId and other middleware context values remain typed.

In `@supabase/functions/_backend/utils/builder_capacity.ts`:
- Around line 261-323: Replace the read-then-insert flow in
recordBuilderCapacityIfChanged with an atomic conditional insert that selects
the latest workers_total, computes delta from it, and inserts only when the
value changes. Execute the operation through getPgClient() or getDrizzleClient()
with transaction-level serialization, such as a table lock or capacity-table
advisory lock, and preserve the existing logging and BuilderCapacityEvent return
behavior.
- Around line 80-88: Document the ascending-by-created_at input precondition on
the exported workersAt function, explicitly stating that callers must provide
sorted events; leave its implementation and reconstructHourlyCapacity behavior
unchanged.
- Around line 338-356: Update the query used by the builder capacity calculation
to select id from both baseline and window_events, then add id as the descending
tiebreaker after created_at ASC in the outer ORDER BY. Preserve the existing
baseline ordering and workersAt processing.
- Around line 175-217: Add AbortSignal.timeout to both builder fetch calls in
the capacity request flow: the runners request and the /ok health check. Use the
existing catch-based degraded fallback when either request exceeds the timeout,
while preserving the current response handling and error logging.
- Around line 121-153: Update reconstructHourlyCapacity and its response types
so hourly waiting is not returned as a misleading constant: either populate
waitingByHour from historical data in getAdminBuilderCapacity, or remove the
waiting field from BuilderCapacityHourPoint and all hourly responses if it is
not an API contract. Ensure the admin chart’s existing workers, used, and free
values remain unchanged.

In `@supabase/migrations/20260806202503_builder_capacity_events.sql`:
- Around line 14-20: Remove the redundant idx_build_requests_started_at index
definition from the migration. Keep idx_build_requests_run_interval with its
composite (started_at, completed_at) key and existing partial predicate
unchanged.

In `@tests/admin-stats.unit.test.ts`:
- Around line 54-61: Update the “accepts the builder capacity metric” test to
use the concurrent test variant by changing its `it` declaration to
`it.concurrent`; leave the synchronous schema-parsing assertions unchanged.

In `@tests/builder-capacity.unit.test.ts`:
- Around line 8-31: Expand the builder-capacity tests with concurrent cases
covering null completed_at values in maxConcurrentUsed, null/undefined/NaN and
valid inputs in isoFromBuilderTimestamp, and invalid or reversed ranges in
reconstructHourlyCapacity. Add isoFromBuilderTimestamp to the existing imports,
and assert the documented results for each case while preserving the current
tests.
🪄 Autofix

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: ASSERTIVE

Plan: Pro

Run ID: 6cc95141-0fcc-4cc5-b106-24149aa5db83

📥 Commits

Reviewing files that changed from the base of the PR and between ec1c4f1 and e381fed.

📒 Files selected for processing (15)
  • src/components/admin/AdminMultiLineChart.vue
  • src/pages/admin/dashboard/builder.vue
  • src/stores/adminDashboard.ts
  • src/types/supabase.types.ts
  • supabase/functions/_backend/private/admin_stats.ts
  • supabase/functions/_backend/public/build/capacity.ts
  • supabase/functions/_backend/public/build/index.ts
  • supabase/functions/_backend/public/build/start.ts
  • supabase/functions/_backend/public/build/status.ts
  • supabase/functions/_backend/triggers/cron_reconcile_build_status.ts
  • supabase/functions/_backend/utils/builder_capacity.ts
  • supabase/functions/_backend/utils/supabase.types.ts
  • supabase/migrations/20260806202503_builder_capacity_events.sql
  • tests/admin-stats.unit.test.ts
  • tests/builder-capacity.unit.test.ts
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • Cap-go/capacitor-updater (manual)

Comment thread src/pages/admin/dashboard/builder.vue
Comment thread supabase/functions/_backend/public/build/capacity.ts Outdated
Comment thread supabase/functions/_backend/utils/builder_capacity.ts
Comment thread supabase/functions/_backend/utils/builder_capacity.ts
Comment thread supabase/functions/_backend/utils/builder_capacity.ts
Comment thread supabase/functions/_backend/utils/builder_capacity.ts
Comment thread supabase/functions/_backend/utils/builder_capacity.ts
Comment thread supabase/migrations/20260806202503_builder_capacity_events.sql Outdated
Comment thread tests/admin-stats.unit.test.ts
Comment thread tests/builder-capacity.unit.test.ts

@cubic-dev-ai cubic-dev-ai 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.

All reported issues were addressed across 8 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread supabase/migrations/20260807121500_builder_capacity_events.sql
Comment thread supabase/functions/_backend/utils/builder_capacity.ts
Rename the capacity migration after main's latest timestamp, drop the
redundant index, type the capacity endpoint context, bound builder
fetches, poll live capacity, and clear the knip unused export.

Co-authored-by: Cursor <cursoragent@cursor.com>
@cursor

cursor Bot commented Aug 7, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_6685c1ed-3f2c-4128-9a38-93ae33e3f076)

@riderx

riderx commented Aug 7, 2026

Copy link
Copy Markdown
Member Author

CI / review follow-up (AI generated)

cab51c182 (+ merge from main):

  • Renamed migration to 20260807121500_... (after 20260807093220 on main) — fixes migration order check
  • Removed unused PrescanOverrideMode export — fixes knip
  • Capacity endpoint typed with Context<MiddlewareKeyVariables>
  • Builder fetches use AbortSignal.timeout(5s)
  • Capacity event query ORDER BY created_at, id
  • Live capacity polls every 30s with forceRefresh
  • Extra unit tests for open intervals / timestamp helpers / invalid ranges

Co-authored-by: Cursor <cursoragent@cursor.com>
@cursor

cursor Bot commented Aug 7, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_47900be6-c216-4ca9-aad3-09591b3bc284)

@riderx
riderx merged commit babf51c into main Aug 7, 2026
73 of 82 checks passed
@riderx
riderx deleted the feat/admin-builder-capacity branch August 7, 2026 10:25
@sonarqubecloud

sonarqubecloud Bot commented Aug 7, 2026

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant