Skip to content

fix: optimize segment queries and add timeout to recipient count#352

Merged
alanw707 merged 1 commit into
mainfrom
fix/segment-query-perf-and-timeout
Apr 10, 2026
Merged

fix: optimize segment queries and add timeout to recipient count#352
alanw707 merged 1 commit into
mainfrom
fix/segment-query-perf-and-timeout

Conversation

@alanw707
Copy link
Copy Markdown
Owner

Summary

  • Rewrote correlated LINQ subqueries in BuildSegmentQuery to non-correlated GroupBy+Contains patterns — EF Core now emits efficient IN (SELECT ...) joins instead of N+1 SELECT COUNT(*) per user row (~30s → <3s)
  • Added missing timeout(12000) to previewSegmentCount() in the campaigns admin UI so the spinner clears after 12s with an error message instead of hanging indefinitely
  • Added user-facing error message when segment count times out or fails

Test plan

  • Select each segment in New Campaign → count resolves in <3s
  • Compare segment counts before/after against direct SQL to confirm correctness
  • Throttle network or kill API → spinner stops at ~12s with error message
  • Campaigns list loads normally (no regression)

🤖 Generated with Claude Code

Rewrite correlated subqueries in BuildSegmentQuery to non-correlated
GroupBy+Contains patterns so EF Core emits efficient joins instead of
N+1 SELECT COUNT(*) calls (~30s → <3s). Add missing 12s timeout to
previewSegmentCount() frontend call to prevent indefinite spinner.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@alanw707 alanw707 merged commit 6532d64 into main Apr 10, 2026
@alanw707 alanw707 deleted the fix/segment-query-perf-and-timeout branch April 10, 2026 05:04
alanw707 added a commit that referenced this pull request Apr 10, 2026
…ndex

The previous segment query rewrite (PR #352) changed C# structure but not
the generated SQL — navigation property Count() inside Select() still
produced a correlated subquery per UserProfile row (~30s).

This rewrites uploadsByUser to use an explicit Join + GroupBy on the
ProcessedImages table, generating a single-pass GROUP BY aggregate that
uses the existing IX_ProcessedImages_UserProfileId_IsOriginalUpload index.

Frontend: remove full-page "Loading…" replacement for the list view — show
the table shell (headers, empty state) immediately so the page feels instant.

Also adds IX_MarketingCampaigns_CreatedAt for the ORDER BY in GetCampaignsAsync,
and fixes the reviews route missing loadComponent (Angular 19 validation).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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.

1 participant