Skip to content

fix: track body truncation explicitly instead of inferring from cap l…#166

Open
greatjourney589 wants to merge 2 commits into
MkDev11:mainfrom
greatjourney589:fix/issue-165-body-truncation-tracking
Open

fix: track body truncation explicitly instead of inferring from cap l…#166
greatjourney589 wants to merge 2 commits into
MkDev11:mainfrom
greatjourney589:fix/issue-165-body-truncation-tracking

Conversation

@greatjourney589
Copy link
Copy Markdown

@greatjourney589 greatjourney589 commented May 26, 2026

Summary

Track issue/PR body truncation with an explicit body_truncated flag instead of
inferring it from the stored body length.

Previously the detail routes decided whether to serve a cached body by comparing
its length to the cap (body.length !== 8000 for issues, !== 4000 for pulls).
This was fragile:

  • A body whose real length happened to equal the cap was treated as truncated
    forever, triggering a fresh GitHub fetch on every poll cycle.
  • A full body stored by an earlier detail open could be silently clobbered back
    to a capped slice by the next poller sweep.
  • The poller's cap and the detail route's inferred cap could drift apart if only
    one side changed.

Now truncation is recorded explicitly:

  • New src/lib/body-cap.ts is the single source of truth for the caps
    (ISSUE_BODY_CAP = 8000, PULL_BODY_CAP = 4000) and exposes capBody(),
    which clamps a body and reports whether it was actually shortened (strict
    > cap, so an exact-length body is not truncated).
  • New body_truncated column on issues/pulls, with a guarded migration that
    backfills existing rows (rows at exactly the cap length are flagged truncated —
    the safe direction, since a false-truncated flag just costs one self-healing
    re-fetch).
  • Detail routes serve from cache only when !body_truncated, and store the full
    uncapped body with the flag cleared.
  • Poller upserts never downgrade a complete body back to a capped slice: a stored
    full body is overwritten only when the incoming body is itself complete, the
    stored body is already truncated, or the incoming text is at least as long.

Related Issues

Fixes #165.

Type of Change

  • Bug fix
  • New feature
  • Enhancement
  • Refactor
  • Documentation
  • Other (describe):

Testing

  • pnpm build passes
  • Manual browser smoke test (for UI changes)
  • N/A — docs / config only

Checklist

  • Self-reviewed the diff
  • Follows existing code patterns and naming
  • No unrelated changes included
  • Documentation updated if behavior changed

Summary by CodeRabbit

  • Bug Fixes
    • Fixed issue and pull request body truncation detection to use explicit tracking instead of inferring from length.
    • Improved caching to preserve complete issue and PR bodies without downgrading stored content on subsequent updates.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 26, 2026

Warning

Review limit reached

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

More reviews will be available in 5 minutes and 38 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 0e58c83d-9edd-4526-aefa-13c3eebe4ddf

📥 Commits

Reviewing files that changed from the base of the PR and between 5e2ea1e and f8521ad.

📒 Files selected for processing (1)
  • src/lib/db.ts
📝 Walkthrough

Walkthrough

This PR introduces explicit body truncation tracking to fix a bug where the poller continuously re-truncates cached issue and pull request bodies, defeating the detail cache and consuming unnecessary GitHub API quota. The implementation adds a body_truncated flag to the database schema, centralizes body capping logic, and updates the poller to prevent downgrading stored full bodies during sweeps.

Changes

Explicit body truncation tracking with no-downgrade poller semantics

Layer / File(s) Summary
Body cap constants and capping utility
src/lib/body-cap.ts
Defines ISSUE_BODY_CAP (8000) and PULL_BODY_CAP (4000) constants and exports CappedBody interface with explicit truncated: 0 | 1 field. Implements capBody() helper that safely handles null/undefined inputs and marks truncation only when original length strictly exceeds the cap (so exact-length bodies are not misclassified).
Database schema extension and migrations
src/lib/db.ts
Imports cap constants and extends issues and pulls table schemas with body_truncated INTEGER NOT NULL DEFAULT 0. Adds migration logic that conditionally introduces the column to existing databases and backfills truncation state by marking rows as truncated when stored body length equals the configured cap. Updates IssueRow and PullRow exported interfaces to include the new field.
Poller body capping with no-downgrade semantics
src/lib/refresh.ts
Replaces direct .slice() calls with capBody() for both issues and PRs, obtaining both capped text and an explicit truncation flag. Implements conditional upsert logic in both issue and PR paths that prevents downgrading a previously stored full (non-truncated) body back to a capped slice during subsequent poll sweeps. Persists body_truncated flag output alongside body text.
Issue detail route cache and upsert updates
src/app/api/issue/[owner]/[name]/[number]/route.ts
Updates cache lookup SQL to select body_truncated and changes cache-serving condition from body-length inference to explicit flag check. Modifies GitHub fetch upsert to include body_truncated in both insert and update columns, explicitly setting it to 0 for full detail bodies. Returns body_truncated: 0 in GitHub fetch JSON response.
Pull detail route cache and upsert updates
src/app/api/pull/[owner]/[name]/[number]/route.ts
Updates cache logic to require cached.body_truncated to be unset (replacing length-based check). Modifies GitHub fetch upsert to include and clear body_truncated on conflict for full detail bodies. Returns body_truncated: 0 in GitHub fetch JSON response.
Related-issues route truncation flag propagation
src/app/api/related-issues/[owner]/[name]/[number]/route.ts
Updates selectPull, fetchPull, and fetchAndCacheIssue to handle the body_truncated flag. Extends selectLinkedIssues and selectRelatedPulls queries to include the truncation flag in their selected columns so downstream consumers receive complete truncation state.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 A rabbit once stored bodies with care,
But the poller would truncate and stare.
Now a flag marks the cut,
No more sweeping the nut,
Full bodies stay safe in their lair! 🌾

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main structural change: replacing fragile length-based inference with explicit body_truncated tracking.
Linked Issues check ✅ Passed All four objectives from issue #165 are met: explicit body_truncated tracking is implemented, poller downgrade logic prevents overwriting full bodies, CAP constants are centralized, and detail caching is preserved.
Out of Scope Changes check ✅ Passed All changes are tightly scoped to issue #165: body truncation tracking, cap centralization, poller upsert logic, and affected routes. No unrelated code changes are present.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@greatjourney589
Copy link
Copy Markdown
Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 26, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

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 `@src/lib/db.ts`:
- Around line 321-330: Wrap the ALTER TABLE and subsequent UPDATE backfill into
a single transaction so the schema addition and backfill are atomic: for both
the issues and pulls branches (the checks using issuesCols.some and
pullsCols.some), begin a transaction (e.g., db.exec('BEGIN') or use the
library's transaction helper), perform db.exec('ALTER TABLE ... ADD COLUMN
body_truncated ...'), then run the prepared UPDATE (the
db.prepare(...).run(ISSUE_BODY_CAP) and db.prepare(...).run(PULL_BODY_CAP)), and
finally COMMIT; ensure you ROLLBACK on error so a partial ALTER without backfill
cannot be left behind.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: bd620d74-1764-42d2-95b8-91e6edc7e854

📥 Commits

Reviewing files that changed from the base of the PR and between aab5b71 and 5e2ea1e.

📒 Files selected for processing (6)
  • src/app/api/issue/[owner]/[name]/[number]/route.ts
  • src/app/api/pull/[owner]/[name]/[number]/route.ts
  • src/app/api/related-issues/[owner]/[name]/[number]/route.ts
  • src/lib/body-cap.ts
  • src/lib/db.ts
  • src/lib/refresh.ts

Comment thread src/lib/db.ts Outdated
@greatjourney589 greatjourney589 force-pushed the fix/issue-165-body-truncation-tracking branch from 099a56e to 5e2ea1e Compare May 26, 2026 16:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant