perf(grpc): batch ListMessages placements; fix JMAP parse folder #418

Merged
KofTwentyTwo merged 2 commits from perf/list-messages-placements into dev 2026-08-15 00:51:49 +00:00
KofTwentyTwo commented 2026-08-15 00:44:23 +00:00 (Migrated from github.com)

Two related pieces of placement cleanup.

1. ListMessages was N+1 on placements

fill_placements called placements_of once per message, so a page of fifty
cost fifty-one queries against the store.

Adds DatabaseEngine::placements_of_batch, which reads a whole set of message
keys and returns them grouped by key, and uses it from the listing path.

  • Chunked at the existing MAX_KEYS_PER_IN_LIST, mirroring
    existing_placements, so the SQLite bind-parameter ceiling stays unreachable
    from outside the store. Duplicate keys are collapsed before chunking, so no
    key's placements can be gathered from two chunks and appended twice.
  • Ordering preserved. Each key's placements come back ordered by folder id
    ascending, exactly as placements_of orders them. primary_placement takes
    the first, and the proto documents Message.folder_id as the lowest-sorting
    folder id, so this is contract, not incidental.

New test placements_of_batch_matches_per_message_placements_of_including_order
proves the batched read equals the per-message read element for element for a
multi-message, multi-placement fixture, asserts folder-id order explicitly,
and covers the repeated-key and unrequested-key cases.

Error handling changes shape: a failed batch now leaves every set on the page
empty and logs once, where before a failure was per message. Both degrade to a
page without placements rather than a failed listing, and the field is additive.

2. parse_email_get_response no longer hardcodes folder_id = "inbox"

The production path was already corrected in #414 (placements are labelled with
the mailbox actually being synced), but the public helper kept its fixed-folder
signature. It now takes the folder id it is parsing for, and the private
parse_email_get_response_in_folder variant the sync loop used to work around
the fixed label is gone — there is one function again. Callers say which mailbox
they mean.

Closes #339

Gate

cargo fmt --all -- --check, cargo check-all, cargo test-all all green.
RUST_TEST_THREADS=2 cargo test-all run three times: 0 / 0 / 0 FAILED lines.

Two related pieces of placement cleanup. ## 1. `ListMessages` was N+1 on placements `fill_placements` called `placements_of` once per message, so a page of fifty cost fifty-one queries against the store. Adds `DatabaseEngine::placements_of_batch`, which reads a whole set of message keys and returns them grouped by key, and uses it from the listing path. - **Chunked** at the existing `MAX_KEYS_PER_IN_LIST`, mirroring `existing_placements`, so the SQLite bind-parameter ceiling stays unreachable from outside the store. Duplicate keys are collapsed before chunking, so no key's placements can be gathered from two chunks and appended twice. - **Ordering preserved.** Each key's placements come back ordered by folder id ascending, exactly as `placements_of` orders them. `primary_placement` takes the first, and the proto documents `Message.folder_id` as the lowest-sorting folder id, so this is contract, not incidental. New test `placements_of_batch_matches_per_message_placements_of_including_order` proves the batched read equals the per-message read element for element for a multi-message, multi-placement fixture, asserts folder-id order explicitly, and covers the repeated-key and unrequested-key cases. Error handling changes shape: a failed batch now leaves every set on the page empty and logs once, where before a failure was per message. Both degrade to a page without placements rather than a failed listing, and the field is additive. ## 2. `parse_email_get_response` no longer hardcodes `folder_id = "inbox"` The production path was already corrected in #414 (placements are labelled with the mailbox actually being synced), but the public helper kept its fixed-folder signature. It now takes the folder id it is parsing for, and the private `parse_email_get_response_in_folder` variant the sync loop used to work around the fixed label is gone — there is one function again. Callers say which mailbox they mean. Closes #339 ## Gate `cargo fmt --all -- --check`, `cargo check-all`, `cargo test-all` all green. `RUST_TEST_THREADS=2 cargo test-all` run three times: 0 / 0 / 0 `FAILED` lines.
Sign in to join this conversation.