Skip to content

Unify slim/UID-flags fetches via FetchMessageInfoOptions#167

Merged
odrobnik merged 3 commits into
mainfrom
unify-fetch-message-info-attributes
May 19, 2026
Merged

Unify slim/UID-flags fetches via FetchMessageInfoOptions#167
odrobnik merged 3 commits into
mainfrom
unify-fetch-message-info-attributes

Conversation

@odrobnik
Copy link
Copy Markdown
Contributor

@odrobnik odrobnik commented May 19, 2026

Summary

Closes #163. Folds the slim and UID+FLAGS fetch variants from the unmerged #160 into the existing FetchMessageInfoCommand / fetchMessageInfo(s) surface via a new FetchMessageInfoOptions OptionSet, rather than adding parallel command and method families.

  • New FetchMessageInfoOptions with .default / .slim / .uidFlagsOnly presets, a newsletterHeaderFields constant, and a suggestedChunkSize derived from per-message payload weight (50 / 500 / 5000).
  • FetchMessageInfoCommand takes options and optional headerFields and builds [FetchAttribute] dynamically. UID is always implicit.
  • fetchMessageInfo, fetchMessageInfosBulk, the range overloads, and the streaming variant gain options: / headerFields: parameters on both IMAPServer and IMAPNamedConnection. All defaulted — existing call sites unchanged.
  • Streaming variant adds chunkSize: Int? override; default comes from options.suggestedChunkSize.
  • Body-structure helpers extracted to a sibling file so IMAPServer+Fetch.swift stays under SwiftLint's 400-line file_length.

How #163's open questions are resolved

  • Result typeMessageInfo is kept for all variants. Skipped fields stay nil. A separate lightweight type would re-fragment what this change is unifying.
  • Chunk-size knob — derived from options for the common case (no API noise), overridable on the streaming variant where chunking actually applies. Replaces the two private let *FetchChunkSize constants from Add slim/UID-flags fetches, mailbox delete & rename, RFC822.SIZE, named US zones #160.

Example call sites

// Unchanged
try await server.fetchMessageInfosBulk(using: uids)

// Newsletter triage scan — use the streaming variant so .slim's 500-per-chunk
// suggestedChunkSize kicks in. fetchMessageInfosBulk on a large mailbox would
// still hit the 10s per-command timeout even with the lighter payload.
for try await info in server.fetchMessageInfos(
    using: uids,
    options: .slim,
    headerFields: FetchMessageInfoOptions.newsletterHeaderFields
) {
    // …
}

// Incremental-sync diff — streams ~5000-per-chunk by default
for try await info in server.fetchMessageInfos(using: uids, options: .uidFlagsOnly) { ... }

Test plan

  • `swift build` clean
  • `swift test` — all 289 tests pass (286 prior + 3 new)
  • `swiftlint lint` on touched files — 0 violations
  • Smoke test against a real IMAP account (`.slim` + `.uidFlagsOnly` paths)

🤖 Generated with Claude Code

odrobnik and others added 2 commits May 19, 2026 08:06
Folds the slim and UID+FLAGS fetch variants from #160 into the existing
FetchMessageInfoCommand / fetchMessageInfo(s) surface via a new
FetchMessageInfoOptions OptionSet, addressing #163.

- Add FetchMessageInfoOptions with .default / .slim / .uidFlagsOnly presets,
  a newsletterHeaderFields constant, and a suggestedChunkSize derived from
  per-message payload weight (50 / 500 / 5000).
- Parameterize FetchMessageInfoCommand with options + optional headerFields,
  building [FetchAttribute] dynamically. UID is always implicit.
- Extend fetchMessageInfo, fetchMessageInfosBulk, range overloads, and the
  streaming variant on IMAPServer and IMAPNamedConnection with options /
  headerFields parameters (all defaulted, existing call sites unchanged).
- Streaming variant gains chunkSize: Int? override; default is derived from
  options.suggestedChunkSize.
- Extract IMAPServer+Fetch body-structure helpers into their own file to
  keep the main file under the SwiftLint file_length threshold.

No new command/handler types. MessageInfo stays the result type for all
variants (the now-skipped fields remain nil).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR unifies lighter-weight message metadata fetch variants into the existing FetchMessageInfoCommand and fetch APIs using FetchMessageInfoOptions, reducing the need for parallel command families while preserving default behavior.

Changes:

  • Adds FetchMessageInfoOptions presets for default, slim, and UID/flags-only fetches.
  • Updates FetchMessageInfoCommand, IMAPServer, and IMAPNamedConnection fetch methods to accept options and targeted header fields.
  • Extracts body-structure helper methods into a separate file and adds option behavior tests.

Reviewed changes

Copilot reviewed 6 out of 7 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
.gitignore Ignores .claude/ local tooling files.
Sources/SwiftMail/IMAP/IMAP/Commands/FetchCommands.swift Builds fetch attributes dynamically from FetchMessageInfoOptions.
Sources/SwiftMail/IMAP/IMAPNamedConnection+Fetch.swift Adds options/header-fields parameters to named-connection bulk and range fetch APIs.
Sources/SwiftMail/IMAP/IMAPServer+BodyStructureHelpers.swift Moves body-structure helper implementation out of IMAPServer+Fetch.swift.
Sources/SwiftMail/IMAP/IMAPServer+Fetch.swift Adds options/header-fields/chunk-size support to server fetch APIs.
Sources/SwiftMail/IMAP/Models/FetchMessageInfoOptions.swift Defines the new fetch option set, presets, newsletter fields, and chunk-size heuristic.
Tests/SwiftIMAPTests/FetchMessageInfoOptionsTests.swift Covers option presets and chunk-size bucketing.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread Sources/SwiftMail/IMAP/IMAPNamedConnection+Fetch.swift
Mirrors the IMAPServer streaming variant so named connections can use the
.slim and .uidFlagsOnly streaming paths without dropping back to the actor.
Same shape: nonisolated, AsyncThrowingStream, chunk size derived from
options.suggestedChunkSize with optional override.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@odrobnik odrobnik merged commit f5c0940 into main May 19, 2026
4 checks passed
@odrobnik odrobnik deleted the unify-fetch-message-info-attributes branch May 19, 2026 07:09
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.

Unify slim / lightweight IMAP FETCH variants with existing fetch methods via attribute options

2 participants