Skip to content

perf(db): functional trip-search index + company.Status + filtered outbox index#18

Merged
kashkoool merged 2 commits into
mainfrom
perf/db-indexes
Jun 2, 2026
Merged

perf(db): functional trip-search index + company.Status + filtered outbox index#18
kashkoool merged 2 commits into
mainfrom
perf/db-indexes

Conversation

@kashkoool

@kashkoool kashkoool commented Jun 2, 2026

Copy link
Copy Markdown
Owner

What

First step of the full-system build-out: tighten DB indexing for the hottest queries (from the PROJECT_STATUS.md DB review).

Changes (migration AddSearchIndexes)

  • Trip search — the query compares lower(origin)/lower(destination) and only wants Scheduled trips, so the old plain (Origin,Destination,DepartureUtc) index could never be used. Replaced with a functional, partial index:
    (lower("Origin"), lower("Destination"), "DepartureUtc") WHERE "Status" = 'Scheduled' (raw SQL — EF's fluent API can't express lower() + partial together).
  • company.Status — indexed so the "active companies" subquery in trip search and the admin list-by-status filter don't table-scan.
  • outbox — replaced the (ProcessedAtUtc, OccurredAtUtc) composite with a partial index on OccurredAtUtc WHERE "ProcessedAtUtc" IS NULL, matching the publisher's exact poll predicate and staying small as processed rows accumulate.

Verification

  • dotnet test50 unit + 18 integration green; the migration applies cleanly to a fresh Postgres (Testcontainers), which exercises the raw functional-index SQL.
  • 0 build warnings.

Part of the phased roadmap (indexes → Google OAuth → staff → payments → notifications/real-time → reports/demand → observability).

Summary by CodeRabbit

  • Documentation

    • Added comprehensive project status document detailing system completion metrics (35-40% overall), feature status by user role, database schema coverage, and prioritized development roadmap.
  • Chores

    • Optimized database indexing for improved search and query performance.

…tbox index

Tighten indexing for the hottest queries (DB review from PROJECT_STATUS):

- trip search: the query compares lower(origin)/lower(destination) and only wants
  Scheduled trips, so the old plain (Origin,Destination,DepartureUtc) index could
  never serve it. Replace it with a functional, partial index
  (lower("Origin"), lower("Destination"), "DepartureUtc") WHERE "Status"='Scheduled'
  (raw SQL — EF's fluent API can't express lower()+partial).
- company.Status: indexed so the "active companies" subquery in trip search and the
  admin list-by-status filter don't table-scan.
- outbox: replace the (ProcessedAtUtc,OccurredAtUtc) composite with a partial index
  on OccurredAtUtc WHERE "ProcessedAtUtc" IS NULL — matches the publisher's exact
  poll predicate and stays small as processed rows accumulate.

Migration AddSearchIndexes. 50 unit + 18 integration green (applies cleanly to a
fresh Postgres via Testcontainers).
@coderabbitai

coderabbitai Bot commented Jun 2, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@kashkoool, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 46 minutes and 55 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

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.

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 include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b5a3c6cd-5512-499b-97ba-cdf22b6a9e2c

📥 Commits

Reviewing files that changed from the base of the PR and between 5a7850c and 8a443d6.

📒 Files selected for processing (1)
  • PROJECT_STATUS.md
📝 Walkthrough

Walkthrough

The PR adds a comprehensive system status document describing authentication, feature completeness (~35–40%), implemented and missing capabilities by actor, database schema coverage, and DevOps status, alongside database index optimizations for Company, OutboxMessage, and Trip entities to improve search and outbox processing performance.

Changes

System Status and Database Index Optimization

Layer / File(s) Summary
Project System Status
PROJECT_STATUS.md
Dated snapshot documenting authentication approach (email/password only), feature completeness by architectural area, actor-based capability checklist (Customer, Vendor/Manager, Admin; Staff actor missing), cross-cutting capabilities (JWT, RBAC, outbox, idempotency; missing observability), current database design (core booking strong; 10+ missing tables), DevOps status (Docker/CI present; cloud/IaC/observability not implemented), and a prioritized roadmap including payments, staff actor, notifications, cloud, and mobile app.
Database Index Optimization
src/TransportPlatform.Infrastructure/Persistence/Configurations/CompanyConfiguration.cs, src/TransportPlatform.Infrastructure/Persistence/Configurations/OutboxMessageConfiguration.cs, src/TransportPlatform.Infrastructure/Persistence/Configurations/TripConfiguration.cs, src/TransportPlatform.Infrastructure/Persistence/Migrations/20260602210228_AddSearchIndexes.cs
EF configurations refactor indexes for search and processing performance: Company adds a Status index for filtering; OutboxMessage replaces a composite index with a filtered index on unprocessed rows (ProcessedAtUtc IS NULL); Trip moves its search index to raw SQL with functional lowercase-based filtering restricted to scheduled trips. Migration drops prior indexes and creates the optimized replacements.

🎯 2 (Simple) | ⏱️ ~12 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and concisely describes the main changes: adding a functional trip-search index, company.Status index, and filtered outbox index for database performance optimization.
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.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch perf/db-indexes

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.

@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: 4

🧹 Nitpick comments (1)
src/TransportPlatform.Infrastructure/Persistence/Migrations/20260602210228_AddSearchIndexes.cs (1)

35-38: Consider table-locking impact of a plain CREATE INDEX on a populated trip table.

A non-concurrent CREATE INDEX holds a lock that blocks writes for the duration of the build. On an empty/fresh DB (as tested via Testcontainers) this is a non-issue, but against a production table with existing rows it can cause write downtime. If this migration will run against populated data, evaluate building with CREATE INDEX CONCURRENTLY — note that requires running outside a transaction, so it would need a separate migration with transaction suppression rather than the default EF migration transaction.

🤖 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
`@src/TransportPlatform.Infrastructure/Persistence/Migrations/20260602210228_AddSearchIndexes.cs`
around lines 35 - 38, The plain CREATE INDEX in AddSearchIndexes
(migrationBuilder.Sql(... "CREATE INDEX \"IX_trip_search\" ON trip ...")) will
take a write lock on populated trip rows; change to build the index concurrently
by issuing CREATE INDEX CONCURRENTLY "IX_trip_search" ... instead, and ensure
this statement runs outside EF's transaction by moving it into a separate
migration or by marking the migration as non-transactional (so the SQL runs
without the default transaction). Update the migration that contains
migrationBuilder.Sql(...) to use the CONCURRENTLY form and ensure the migration
class is configured to run without a transaction (so the concurrent index
creation is allowed).
🤖 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 `@PROJECT_STATUS.md`:
- Line 3: The snapshot metadata line "Snapshot date: 2026-06-02 · Branch
scanned: `main` (after PR `#17`)" is incorrect for this PR and the documented
index structures referenced later will be outdated; update that snapshot
metadata to "after PR `#18`" and edit the index descriptions that currently
describe the old schema (the index blocks around the current index description
entries) to reflect the index changes introduced by this PR, or alternatively
replace the index descriptions with a short note that index changes are pending
and will be finalized when PR `#18` merges; ensure the snapshot header string and
the index description sections are consistent.
- Around line 175-178: The trip table's documentation still lists the old index
on (Origin,Destination,DepartureUtc); update it to describe the new functional
partial index that supports case-insensitive search and only indexes scheduled
trips by replacing that index description with: a functional, partial index on
(lower("Origin"), lower("Destination"), "DepartureUtc") WHERE "Status" =
'Scheduled' (reference: trip table, index on Origin/Destination/DepartureUtc,
and the lower(...) functional expressions and WHERE "Status" = 'Scheduled').
- Around line 168-169: Add documentation for the new index IX_company_Status
under the company schema in PROJECT_STATUS.md: state that IX_company_Status is
an index on company.Status (varchar(20)) and briefly describe its purpose—to
speed filtering for "active companies" subqueries and admin list-by-status
operations (avoiding table scans); place the note adjacent to the company schema
line that lists `Status` so readers can see the index and its intent together.
- Around line 200-201: Update the outbox_message index docs to describe the new
filtered index: replace the old composite index note `(ProcessedAtUtc,
OccurredAtUtc)` with a description that there is now a filtered index on
OccurredAtUtc WHERE "ProcessedAtUtc" IS NULL (to match the publisher poll
predicate and remain small as processed rows accumulate), and mention which
columns are covered (`OccurredAtUtc`) and the filter on `ProcessedAtUtc`; keep
the rest of the schema line intact.

---

Nitpick comments:
In
`@src/TransportPlatform.Infrastructure/Persistence/Migrations/20260602210228_AddSearchIndexes.cs`:
- Around line 35-38: The plain CREATE INDEX in AddSearchIndexes
(migrationBuilder.Sql(... "CREATE INDEX \"IX_trip_search\" ON trip ...")) will
take a write lock on populated trip rows; change to build the index concurrently
by issuing CREATE INDEX CONCURRENTLY "IX_trip_search" ... instead, and ensure
this statement runs outside EF's transaction by moving it into a separate
migration or by marking the migration as non-transactional (so the SQL runs
without the default transaction). Update the migration that contains
migrationBuilder.Sql(...) to use the CONCURRENTLY form and ensure the migration
class is configured to run without a transaction (so the concurrent index
creation is allowed).
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: a528b7a7-4343-4096-9568-461aebf4b2a4

📥 Commits

Reviewing files that changed from the base of the PR and between 912a597 and 5a7850c.

⛔ Files ignored due to path filters (3)
  • src/TransportPlatform.Infrastructure/Persistence/Migrations/20260602210228_AddSearchIndexes.Designer.cs is excluded by !**/Migrations/*.Designer.cs
  • src/TransportPlatform.Infrastructure/Persistence/Migrations/ApplicationDbContextModelSnapshot.cs is excluded by !**/Migrations/*ModelSnapshot.cs
  • web/customer/package-lock.json is excluded by !**/package-lock.json, !**/package-lock.json
📒 Files selected for processing (5)
  • PROJECT_STATUS.md
  • src/TransportPlatform.Infrastructure/Persistence/Configurations/CompanyConfiguration.cs
  • src/TransportPlatform.Infrastructure/Persistence/Configurations/OutboxMessageConfiguration.cs
  • src/TransportPlatform.Infrastructure/Persistence/Configurations/TripConfiguration.cs
  • src/TransportPlatform.Infrastructure/Persistence/Migrations/20260602210228_AddSearchIndexes.cs

Comment thread PROJECT_STATUS.md Outdated
Comment thread PROJECT_STATUS.md Outdated
Comment thread PROJECT_STATUS.md Outdated
Comment thread PROJECT_STATUS.md Outdated
PROJECT_STATUS.md was swept into this PR; sync its DB-design section with the
AddSearchIndexes migration (functional partial trip-search index, company.Status
index, filtered outbox index) per review.
@kashkoool kashkoool merged commit aad92cf into main Jun 2, 2026
9 checks passed
@kashkoool kashkoool deleted the perf/db-indexes branch June 2, 2026 21:24
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