Skip to content

fix(lists): get_entry cursor scope + reorder rollback on failure (tsk-u23vjy) - #2361

Merged
jaylfc merged 2 commits into
devfrom
exec/tsk-u23vjy-v2
Aug 11, 2026
Merged

fix(lists): get_entry cursor scope + reorder rollback on failure (tsk-u23vjy)#2361
jaylfc merged 2 commits into
devfrom
exec/tsk-u23vjy-v2

Conversation

@jaylfc

@jaylfc jaylfc commented Aug 11, 2026

Copy link
Copy Markdown
Owner

Lead completion of board card tsk-u23vjy (bounced PR #2359 — analysis there). Re-scoped against what is actually true on dev:

Card defects 1 and 2 need no code. Position-0 collision is already fixed on dev by #2265's atomic in-INSERT allocation, guarded by test_concurrent_add_entry_distinct_positions (which #2359 had rewritten into a sequential test — restored untouched here). NULL list_id rows are structurally impossible: the schema says list_id TEXT NOT NULL, so the IS-NULL branch the card asks for is dead code on arrival (proven: inserting list_id=None raises IntegrityError). _get_next_position itself has zero callers on dev. The card's acceptance criteria were written against the closed duplicate PR #2183's branch, where both defects were real.

Defects 3 and 4 are real and land here.

Red-first evidence (lead-run at merge ref)

The rollback test executed against dev's unguarded reorder_entries:

FAILED tests/projects/test_lists_store.py::test_reorder_entries_rolls_back_on_exception
1 failed in 0.38s

The failure mode is the card's exact hazard: the first UPDATE stays pending on the shared connection after the exception, and the assertion catches the half-applied position. With the fix, 19/19 pass. The get_entry cursor fix is latent-hazard hardening (aiosqlite's closed cursor happens to retain description today), so no red is possible for it; stated honestly rather than manufactured.

Timing/atomicity statement

reorder_entries' single-commit atomicity is untouched (the card forbids restructuring it); the change only adds rollback + re-raise on the failure path.

Summary by CodeRabbit

  • Bug Fixes

    • Project list entries can now be retrieved reliably.
    • Failed list reordering operations fully roll back partial changes, preventing incomplete ordering updates from being saved.
  • Tests

    • Added regression coverage for entry retrieval and rollback behavior.
  • Documentation

    • Added a changelog entry describing these fixes.

…k-u23vjy)

Re-scoped fix-forward of closed duplicate PR #2183. Of the card's four
defects, two are already resolved or impossible on dev: position-0
collision was fixed by #2265's atomic in-INSERT allocation (existing
concurrency test guards it), and NULL list_id rows cannot exist (schema
NOT NULL). The two real ones land here:

- get_entry read cur.description outside the cursor context; moved inside.
- reorder_entries left already-issued UPDATEs pending when one raised, so
  the next unrelated commit() flushed a half-applied reorder; now rolls
  back and re-raises, with a test proving the pending write neither
  survives immediately nor resurfaces via a later unrelated commit
  (proven red against the unguarded store).
@qodo-code-review

Copy link
Copy Markdown

ⓘ Qodo reviews are paused because the subscription is no longer active. Ask your workspace admin to reactivate the subscription to resume reviews. Manage billing

@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: cd561ac2-39e5-471a-8ee9-a6b15dc16124

📥 Commits

Reviewing files that changed from the base of the PR and between 2c5c8a3 and 2fee937.

📒 Files selected for processing (2)
  • tests/projects/test_lists_store.py
  • tinyagentos/projects/lists_store.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • tinyagentos/projects/lists_store.py

📝 Walkthrough

Walkthrough

The project list store now builds entry metadata while the cursor remains open and rolls back partial reorder updates when updates, cancellation, or commit operations fail. Regression tests and a changelog entry document these fixes.

Changes

Project list store fixes

Layer / File(s) Summary
List entry retrieval
tinyagentos/projects/lists_store.py, tests/projects/test_lists_store.py
get_entry derives result fields before cursor closure. Tests verify the returned entry and its fields.
Reorder rollback handling
tinyagentos/projects/lists_store.py, tests/projects/test_lists_store.py, changelog.d/2361-lists-store-cursor-rollback.md
reorder_entries rolls back pending updates when an update, cancellation, or commit fails. Tests verify that later writes do not persist partial ordering changes. The changelog records both fixes.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

  • jaylfc/taOS#2265: Both changes cover rollback behavior for partial reorder_entries updates.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 23.08% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely identifies both primary fixes: cursor scope in get_entry and rollback on reorder failure.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch exec/tsk-u23vjy-v2

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.

@gitar-bot

gitar-bot Bot commented Aug 11, 2026

Copy link
Copy Markdown

Gitar is working

Gitar

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

🧹 Nitpick comments (1)
tinyagentos/projects/lists_store.py (1)

179-179: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Set strict=True on zip.

Ruff reports B905 on Line 179. Use zip(keys, row, strict=True) so an unexpected column-value mismatch fails immediately.

🤖 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 `@tinyagentos/projects/lists_store.py` at line 179, Update the dict
construction in the row-mapping method around dict(zip(keys, row)) to call zip
with strict=True, ensuring mismatched key and value lengths fail immediately.

Source: Linters/SAST tools

🤖 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 `@tests/projects/test_lists_store.py`:
- Around line 351-397: Extend the reorder rollback tests around
test_reorder_entries_rolls_back_on_exception with separate cases for
asyncio.CancelledError during the second position UPDATE and an exception from
commit(). In each case, invoke reorder_entries with the swapped positions,
restore any monkeypatches, perform an unrelated add_entry(), and assert both
original entries still have their initial positions.

In `@tinyagentos/projects/lists_store.py`:
- Around line 263-279: The reorder transaction spanning
tinyagentos/projects/lists_store.py:263-279 must include both the UPDATE loop
and commit within rollback-protected handling, explicitly covering
asyncio.CancelledError as well as ordinary exceptions before re-raising. Add
tests in tests/projects/test_lists_store.py:351-397 for cancellation during a
later UPDATE and for commit failure, asserting rollback occurs and partial
changes are not persisted.

---

Nitpick comments:
In `@tinyagentos/projects/lists_store.py`:
- Line 179: Update the dict construction in the row-mapping method around
dict(zip(keys, row)) to call zip with strict=True, ensuring mismatched key and
value lengths fail immediately.
🪄 Autofix

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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 6b055fcc-2787-4007-896d-a075965071f4

📥 Commits

Reviewing files that changed from the base of the PR and between e55ecfb and 2c5c8a3.

📒 Files selected for processing (3)
  • changelog.d/2361-lists-store-cursor-rollback.md
  • tests/projects/test_lists_store.py
  • tinyagentos/projects/lists_store.py

Comment thread tests/projects/test_lists_store.py
Comment thread tinyagentos/projects/lists_store.py Outdated
@kilo-code-bot

kilo-code-bot Bot commented Aug 11, 2026

Copy link
Copy Markdown

Code Review Summary

Status: 1 Issue Found | Recommendation: Address before merge

Overview

Severity Count
WARNING 1
Issue Details (click to expand)

WARNING

File Line Issue
tinyagentos/projects/lists_store.py 274 except BaseException catches SystemExit and KeyboardInterrupt, which could suppress process-exit signals if rollback() fails during shutdown or interrupt handling. Consider narrowing to except (Exception, asyncio.CancelledError): to catch only the intended exceptions.
Files Reviewed (2 files)
  • tinyagentos/projects/lists_store.py - 1 issue
  • tests/projects/test_lists_store.py

Fix these issues in Kilo Cloud

Previous Review Summary (commit 2c5c8a3)

Current summary above is authoritative. Previous snapshots are kept for context only.

Previous review (commit 2c5c8a3)

Status: No Issues Found | Recommendation: Merge

Files Reviewed (3 files)
  • changelog.d/2361-lists-store-cursor-rollback.md
  • tests/projects/test_lists_store.py
  • tinyagentos/projects/lists_store.py

Reviewed by step-3.7-flash · Input: 66.1K · Output: 33.8K · Cached: 617.3K

@jaylfc

jaylfc commented Aug 11, 2026

Copy link
Copy Markdown
Owner Author

nemotron-super review

VERDICT: No blocking issues found
No blocking issues found

Automated first-pass review by the nemotron-super lane. The lead still reviews before merge.

…it()

CodeRabbit's Major on #2361, folded: asyncio.CancelledError does not
inherit Exception, so task cancellation mid-reorder left the issued
UPDATEs pending exactly like the original hazard, and commit() sat
outside the guard. The commit moves inside the try and the handler
catches BaseException, rolling back before re-raising. Regression tests
for both paths; the cancellation test proven red against the
except-Exception guard.
@jaylfc

jaylfc commented Aug 11, 2026

Copy link
Copy Markdown
Owner Author

Both CodeRabbit findings folded: the Major was real — CancelledError bypasses except Exception, so cancellation mid-reorder left pending UPDATEs (the exact hazard class), and commit() sat outside the guard. Guard now catches BaseException with commit() inside the try. Regression tests added for cancellation and commit failure, each asserting the half-applied positions do not resurface via a later unrelated commit; the cancellation test proven red against the narrow guard. 21/21 pass.

await self._db.rollback()
return False
await self._db.commit()
except BaseException:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[WARNING]: except BaseException catches SystemExit and KeyboardInterrupt

except BaseException is broader than needed. It captures SystemExit and KeyboardInterrupt, which could suppress process-exit signals if rollback() fails during shutdown or interrupt handling. Consider narrowing to except (Exception, asyncio.CancelledError): to catch only the intended exceptions.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

@jaylfc
jaylfc merged commit ef7fadd into dev Aug 11, 2026
21 checks passed
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