Repository navigation
ref(change-stream): Make ChangeStream async, fallible, and cover before/after commit - #677
Conversation
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #677 +/- ##
==========================================
- Coverage 91.38% 91.33% -0.05%
==========================================
Files 117 117
Lines 24056 24171 +115
==========================================
+ Hits 21983 22077 +94
- Misses 2073 2094 +21
☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
5d8c093 to
7fd1b64
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Want reviews to match your repository better? Bugbot Learning can learn team-specific rules from PR activity. A team admin can enable Learning in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 7fd1b64. Configure here.
| }), | ||
| ) | ||
| .await; | ||
| } |
There was a problem hiding this comment.
Multipart commit skips expired objects
Medium Severity
After a successful multipart complete, size and expiry are taken from get_gcs_metadata, which returns none for expired objects and whose errors are discarded. report_object_write then skips commit_write, so a stored object is omitted from the change stream. Long uploads that outlive their TTL are the typical trigger; put_object does not have this gap because it reads size from the upload response.
Reviewed by Cursor Bugbot for commit 7fd1b64. Configure here.


Closes FS-565
For a GC
ChangeStream:.awaited and finished before returning, not fire-and-forgetwrite: the object is invisible to GC and leaks foreverupdate: the GC inventory has the wrong expiration time for the object and can delete it prematurelydelete: this is actually okayThis PR addresses these issues:
async fnnowResult<>so the caller can abort the request if an essential change stream failswrite()andupdate()have been split intobegin_{op}andcommit_{op}so different streams can hook the right placesAs a result, a GC
ChangeStreamwould be "inconsistent but safe":begin_write()succeeds but the backend commit fails, the GC will see a harmless ghost object and delete it laterbegin_update()succeeds but the backend commit fails, the GC will see a later expiration time than is actually set on the object and delay cleanupcommit_delete()fails, the GC will see a harmless ghost object and delete it laterAs a drive-by fix: this PR adds a missing
ChangeStream::commit_writein GCS'scomplete_multipart.Note
A non-goal of this PR is safety amidst concurrent requests. That's a different discussion.