chore: improve Cursor error delivery and defer logic#1050
Conversation
There was a problem hiding this comment.
Pull Request Overview
The PR refactors the Cursor method to remove its error return and instead send any iteration or setup errors through the returned channel, while also ensuring proper resource cleanup.
- Simplifies
Cursorsignature tochan Rowand delivers errors via aRow.errfield. - Adds
Err()to theRowstruct/interface and updates mocks accordingly. - Ensures channel closure and resource deferral even on early errors.
Reviewed Changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| tests/query_test.go | Updated test to drop error return from Cursor() and assert row.Err() |
| tests/go.mod | Bumped indirect google.golang.org/genproto dependency |
| mocks/database/orm/Query.go | Removed error return from mocked Cursor() signature |
| mocks/database/db/Row.go | Added mock support for new Row.Err() method |
| database/gorm/row.go | Added err field and Err() method to Row; guard Scan on err |
| database/gorm/query.go | Refactored Cursor() to push errors into the channel and defer cleanup |
| contracts/database/orm/orm.go | Changed Cursor() signature to drop error return |
| contracts/database/db/db.go | Added Err() to Row interface |
Comments suppressed due to low confidence (2)
database/gorm/query.go:176
- Errors that occur on the initial
rows.Next()call (before entering the loop) aren’t checked, so they may be silently dropped. After the loop, add a check forrows.Err()(e.g.,if errRows := rows.Err(); errRows != nil { err = errRows }) to ensure all iteration errors are delivered.
for rows.Next() {
tests/query_test.go:577
- [nitpick] There’s no test covering the error delivery path of
Cursor(). Consider adding a test that simulates an error fromRows()orScanRows()and asserts thatrow.Err()yields that error.
func (s *QueryTestSuite) TestCursor() {
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## master #1050 +/- ##
=======================================
Coverage 70.54% 70.54%
=======================================
Files 176 176
Lines 12330 12330
=======================================
Hits 8698 8698
Misses 3252 3252
Partials 380 380 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
hwbrzzl
left a comment
There was a problem hiding this comment.
LGTM, can we add some test cases for the error flow?
I’ll add some basic error flow tests. Other scenarios are hard to simulate without mocking or a more complex setup. |
hwbrzzl
left a comment
There was a problem hiding this comment.
Great PR 👍 Could you fix the gorm query for the v1.15.x branch as well? They are a bit different, only need to fix the memory leak, don't make a breaking change for the Cursor function.
Okay |
📑 Description
What’s Changed
Query.Cursor()to simplify the return signature by removing the(chan, error)tuple.Rowstruct with theerrfield set.Rows.Close()) is handled reliably even in case of early errors.Why
Previously, errors in goroutine setup (e.g.,
query.instance.Rows()) were only returned via the outer error return, which could be misleading since the channel would never yield results. This refactor ensures a more Go-idiomatic pattern: the channel always closes, and all consumers can handle errors uniformly through the same channel.Potential Impact
Downstream consumers of
Cursor()should now checkRow.errto determine if an error occurred, instead of relying on the function's return error.Example Usage (Updated)
✅ Checks