Skip to content

[BUG] GET /api/streams returns stale progress after stream is canceled via API - #664

Open
barnabasolutayo-lgtm wants to merge 1 commit into
ritik4ever:mainfrom
barnabasolutayo-lgtm:api/streams
Open

[BUG] GET /api/streams returns stale progress after stream is canceled via API#664
barnabasolutayo-lgtm wants to merge 1 commit into
ritik4ever:mainfrom
barnabasolutayo-lgtm:api/streams

Conversation

@barnabasolutayo-lgtm

@barnabasolutayo-lgtm barnabasolutayo-lgtm commented Jul 26, 2026

Copy link
Copy Markdown

##closes #600

Move cache invalidation to after DB transaction in cancelStream to prevent race condition. Also fix duplicate variable declarations in calculateProgress.

What changed

Testing done

Related issues

Closes #

Checklist

  • I kept the change focused on the related issue.
  • I added or updated tests where useful.
  • I updated documentation where behavior changed.
  • I verified the app still builds or explained why verification was skipped.

Summary by CodeRabbit

  • Bug Fixes
    • Corrected vesting progress calculations for paused streams and zero-duration streams.
    • Improved cancellation consistency by ensuring updated stream status is saved before related cached data is refreshed.

Move cache invalidation to after DB transaction in cancelStream to prevent race condition. Also fix duplicate variable declarations in calculateProgress.
@vercel

vercel Bot commented Jul 26, 2026

Copy link
Copy Markdown

Someone is attempting to deploy a commit to the ritik4ever's projects Team on Vercel.

A member of the Team first needs to authorize it.

@drips-wave

drips-wave Bot commented Jul 26, 2026

Copy link
Copy Markdown

@barnabasolutayo-lgtm Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@coderabbitai

coderabbitai Bot commented Jul 26, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Updates stream vesting progress calculations and changes cancellation ordering so database state is committed before related caches are invalidated.

Changes

Stream consistency updates

Layer / File(s) Summary
Vesting progress calculation
backend/src/services/streamStore.ts
calculateProgress derives non-negative elapsed time from the effective timestamp and paused duration, and treats non-positive durations as fully vested.
Cancellation persistence and cache invalidation
backend/src/services/streamStore.ts
cancelStream records the canceled stream and event in the database before invalidating stream, list, export, statistics, and metrics caches.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

Suggested reviewers: chkm001, 0xdevmes, libby-coder

🚥 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 describes the primary bug fix in stream cancellation and stale API state.
Linked Issues check ✅ Passed The PR updates cancelStream to commit the canceled status before cache invalidation, matching the issue's SQLite and stale-cache requirements.
Out of Scope Changes check ✅ Passed The changes stay focused on the reported stale-progress bug and related progress calculation cleanup.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ 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.

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
backend/src/services/streamStore.ts (1)

457-458: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Do not report future zero-duration streams as fully vested.

When at < stream.startAt, computeStatus returns "scheduled", but this branch sets ratio to 1 unconditionally for durationSeconds <= 0. The response can therefore be scheduled while showing 100% completion and the full vested amount.

Proposed fix
-  const ratio = stream.durationSeconds <= 0 ? 1 : Math.min(1, elapsed / stream.durationSeconds);
+  const ratio =
+    stream.durationSeconds <= 0
+      ? effectiveAt >= stream.startAt ? 1 : 0
+      : Math.min(1, elapsed / stream.durationSeconds);
🤖 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 `@backend/src/services/streamStore.ts` around lines 457 - 458, Update the ratio
calculation in computeStatus so zero-duration streams that have not started
remain at 0% rather than being treated as fully vested; preserve the existing
100% behavior for zero-duration streams whose start time has been reached, and
keep elapsedSeconds consistent with that status.
🤖 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 `@backend/src/services/streamStore.ts`:
- Around line 1187-1192: Update the post-commit cache invalidation in
cancelStream to make each invalidateCache call resilient to rejection, using
Promise.allSettled or equivalent failure handling and logging any invalidation
errors. Ensure resetStatsCache() and resetStreamMetricsCache() always execute
after the committed mutation, while continuing to access the cache through
getCache() and reset stats via resetStatsCache().

---

Outside diff comments:
In `@backend/src/services/streamStore.ts`:
- Around line 457-458: Update the ratio calculation in computeStatus so
zero-duration streams that have not started remain at 0% rather than being
treated as fully vested; preserve the existing 100% behavior for zero-duration
streams whose start time has been reached, and keep elapsedSeconds consistent
with that status.
🪄 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: feca7df6-a0d2-4bee-b350-85af745ed9a2

📥 Commits

Reviewing files that changed from the base of the PR and between b3d32c1 and 4ad9488.

📒 Files selected for processing (1)
  • backend/src/services/streamStore.ts

Comment on lines +1187 to +1192
// Invalidate cache after DB commit so the next read picks up canceled status.
await invalidateCache(`stream:${id}`);
await invalidateCache("streams:list:");
await invalidateCache("streams:export:");
resetStatsCache();
resetStreamMetricsCache();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Make post-commit cache invalidation resilient.

If any getCache().del() call rejects, cancelStream throws after the SQLite transaction has committed, so the API can return 500 while resetStatsCache() and resetStreamMetricsCache() are skipped. Run invalidations independently with Promise.allSettled or try/finally, log failures, and always reset dependent caches.

As per coding guidelines, backend TypeScript code must access the in-memory LRU cache through getCache() and call resetStatsCache() after mutations that affect stats.

🤖 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 `@backend/src/services/streamStore.ts` around lines 1187 - 1192, Update the
post-commit cache invalidation in cancelStream to make each invalidateCache call
resilient to rejection, using Promise.allSettled or equivalent failure handling
and logging any invalidation errors. Ensure resetStatsCache() and
resetStreamMetricsCache() always execute after the committed mutation, while
continuing to access the cache through getCache() and reset stats via
resetStatsCache().

Source: Coding guidelines

@ritik4ever

Copy link
Copy Markdown
Owner

Hi @barnabasolutayo-lgtm,

This PR could not be merged because it has merge conflicts with the target branch.

Please resolve the merge conflicts, push the updated changes, and the PR can be reviewed and merged.

Thank you!

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.

[BUG] GET /api/streams returns stale progress after stream is canceled via API

2 participants