Skip to content

Reduce Today schedule candidate reads for #790 - #615

Merged
thomasluizon merged 3 commits into
mainfrom
fix/ticket-790-today-candidates
Sep 27, 2026
Merged

thomasluizon merged 3 commits into
mainfrom
fix/ticket-790-today-candidates

Conversation

@thomasluizon

@thomasluizon thomasluizon commented Sep 27, 2026 •

Copy link
Copy Markdown
Owner

Closes thomasluizon/orbit-tickets#790

Change

GetHabitScheduleQuery.cs now projects schedule candidates through HabitScheduleCandidate.cs, using the schedule fields plus title and position. Description and tags join the candidate read only when search or tag filtering needs them. After filtering and paging, the handler fetches complete Habit rows for the selected roots and descendants, then uses the existing page loader for logs, tags, and goals. Habit.cs materializes the candidate fields for the existing schedule rules. The schedule handler and widget parity test mocks now exercise the projected read. HabitScheduleReadShapeTests.cs checks the SQL column list, page-only full-row loading, and search by description and tag.

This keeps both date and non-date response paths on the same candidate and page hydration flow. The response contract is unchanged.

Candidate read evidence

Before, the ticket's production sample recorded 41,071 rows across 60 calls, or 684.5 rows per call. The mean full-row width was 354 bytes using pg_column_size(h.*), giving 242,319 bytes per call for the candidate read.

After, the SQLite relational test emitted this candidate SQL for a request without search or tag filters:

SELECT "h"."Id", "h"."ParentHabitId", "h"."FrequencyUnit", "h"."FrequencyQuantity", "h"."IntervalWeeks", "h"."DueDate", "h"."ScheduledStartDate", "h"."OriginalDayOfMonth", "h"."EndDate", "h"."CreatedAtUtc", "h"."DeletedAtUtc", "h"."IsDeleted", "h"."IsBadHabit", "h"."IsCompleted", "h"."IsGeneral", "h"."IsFlexible", "h"."Days", "h"."Title", "h"."Position"
FROM "Habits" AS "h"
WHERE NOT ("h"."IsDeleted") AND "h"."UserId" = @userId AND NOT ("h"."IsGeneral")

The candidate row count remains one per owned non-general habit, so the same production workload would read 684.5 candidate rows per call. Production access was prohibited for this worker, so the new pg_column_size width is not measured. A column-list estimate removes the 83-byte average Description from the 354-byte full-row width and leaves the other omitted columns uncredited. That gives an upper estimate of 271 bytes per candidate row and 185,504 bytes per call. The actual width needs measurement on a deployed query before it can be stated as a production result. The test observed two candidate rows and a full-row fetch limited to the one page item.

Measured width (orchestrator, read-only on production, 2026-09-27): over the live non-general habits, the average pg_column_size(row(...)) of the 19 candidate columns above is 167 bytes, against 348 bytes for the full row over the same rows. At the recorded 684.5 candidate rows per call that is about 114 KB per call instead of about 238 KB, plus full rows for the page items only. The deployed rows per call are recorded on the ticket after merge.

Test evidence

  • Existing TodayPage_MaterializesOnlyPageLogsWithinTheResponseWindow passed with the defect present at baseline commit 43d847ec: env -u LANG dotnet test tests/Orbit.Infrastructure.Tests --filter FullyQualifiedName~TodayPage_MaterializesOnlyPageLogsWithinTheResponseWindow --logger 'console;verbosity=normal' returned exit 0, one test passed.
  • Strengthened TodayCandidates_ReadOnlyFilterColumns_AndPageRetainsDisplayFields failed against the same baseline with its test file copied into a detached worktree: env -u LANG dotnet test tests/Orbit.Infrastructure.Tests --filter FullyQualifiedName~TodayCandidates_ReadOnlyFilterColumns_AndPageRetainsDisplayFields --logger 'console;verbosity=normal' returned exit 1 because candidate SQL contained Description and ChecklistItems.
  • The strengthened test passed after the fix using the same filter. GetHabitScheduleQueryHandlerTests passed 81 tests and HabitScheduleReadShapeTests passed 5 tests.
  • env -u LANG dotnet build Orbit.slnx completed with 0 errors. env -u LANG dotnet test passed all 6,755 tests across Domain, Analyzers, Application, and Infrastructure.

Assumptions

  • Description is a candidate field only for a nonblank search; omitting it for all searches was rejected because description matches are part of the existing filter.
  • The after bytes per call are a column-list estimate using the ticket's production baseline; claiming a measured production width before deployment was rejected because production database access is prohibited for this worker.

@pullfrog pullfrog 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.

✅ No new issues found.

Reviewed changes Candidate projection, schedule filtering and page hydration for dated and undated Today responses, plus query and relational tests.

  • Candidate reads: Non-general habits now load schedule fields, title and position, adding description and tags only when filters require them.
  • Page hydration: Selected roots and descendants load complete habit rows and page relations before response mapping; the response DTO remains unchanged.
  • Coverage: Updated handler and widget substitutes exercise the projected read, while SQLite tests inspect column selection, page scope, and description and tag search.

Pullfrog  | View workflow run | Using GPT Sol | 𝕏

@sonarqubecloud

Copy link
Copy Markdown

@thomasluizon
thomasluizon merged commit a2312d6 into main Sep 27, 2026
29 checks passed
@thomasluizon
thomasluizon deleted the fix/ticket-790-today-candidates branch September 27, 2026 14:00
thomasluizon added a commit that referenced this pull request Sep 27, 2026
* Reduce Today schedule candidate reads for #790 (#615)

* fix: project Today schedule candidates before page hydration

* test: adapt widget schedule parity setup to candidate projection

* test: report emitted Today candidate SQL

(cherry picked from commit a2312d6)

* Fix Today schedule candidate consistency (#617)

(cherry picked from commit 392b224)
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