Skip to content

Account-scoped sync, if_in_state, paged search_events - #71

Merged
SashankBhamidi merged 1 commit into
mainfrom
feat/jmap-sync-pagination
Oct 18, 2026
Merged

SashankBhamidi merged 1 commit into
mainfrom
feat/jmap-sync-pagination

Conversation

@SashankBhamidi

Copy link
Copy Markdown
Member

Closes #68.
Closes #69.

create_event, send_invite, update_event, and delete_event now accept an optional if_in_state. When the account's state has moved past it, the server rejects the write with stateMismatch rather than applying over a change you never saw.

get_objects_by_sync_token and get_tasks_by_sync_token now return one page at a time. Previously, hasMoreChanges: true made the client raise and the page's newState was lost. The return shape moves from a 4-tuple to a 6-tuple: (added, modified, deleted, old_state, new_state, has_more_changes). Call again with new_state when has_more_changes is true. I changed this from what #69 originally described, which had the method follow every page itself and merge them into a single result before returning. A caller interrupted mid-sync needs to persist progress between pages, and a merged result gives it nothing to persist, so I rewrote the issue text to match what's here. Both methods also take an optional max_changes, to bound a page or to force paging in a test.

get_sync_token, get_objects_by_sync_token, get_task_sync_token, and get_tasks_by_sync_token take an optional account_id now, the same parameter every other account-aware method on this client already has. Neither method had it before. There was no issue filed for this specifically, it was small enough to fix alongside the rest of this PR.

search_events takes position, limit, and calculate_total now, and returns an EventSearchResult instead of a bare list. .events is what the method used to return on its own. .position and .total come straight from the server's CalendarEvent/query response. .total is set only when calculate_total=True was actually passed, never inferred from whether the server's response happened to include one, because Cyrus sends total back unconditionally even when calculateTotal was never requested, against what the spec says it should do. This is a breaking change to search_events's return type, and it had no issue filed either, same reasoning as above.

#67 stays out of this PR. It depends on #66 landing first.

@SashankBhamidi
SashankBhamidi removed the request for review from stevepiercy October 18, 2026 19:03
@codecov

codecov Bot commented Oct 18, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 99.24812% with 3 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/calendaring_jmap/client.py 92.10% 1 Missing and 2 partials ⚠️

📢 Thoughts on this report? Let us know!

@SashankBhamidi
SashankBhamidi merged commit bfebe43 into main Oct 18, 2026
14 checks passed
@SashankBhamidi
SashankBhamidi deleted the feat/jmap-sync-pagination branch October 18, 2026 19:06
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.

Follow hasMoreChanges in get_objects_by_sync_token ifInState on event writes

1 participant