Skip to content

Concurrency Cancellation and Errors

QenTerra edited this page Jul 29, 2026 · 1 revision

Concurrency, Cancellation, and Errors

The project enables Swift 6 with complete strict-concurrency checking.

Isolation model

Boundary Isolation
Observable application and setup state @MainActor
TDLib requests and pending continuations TDLibClient actor
Telegram session lifecycle TelegramSessionController actor
Chat normalization ChatRepository actor
History scanning AttachmentHistoryService actor
Download scheduling DownloadCoordinator actor
Destination bookmark and placement DestinationAccess actor
JSON persistence One actor per store
Cross-boundary domain data Value types conforming to Sendable

TDLibReceiveLoop is marked @unchecked Sendable because it wraps the blocking native receive boundary. Its surface is deliberately small and feeds ordered values into actor-isolated Swift state.

Attachment scan cancellation

Every scan receives a unique scan ID and an AttachmentScanKey. Progress is accepted only if:

  • the scan ID is still active;
  • the cache's active key matches;
  • the currently requested chat and range still match.

Leaving Browse, changing chat, changing range, refreshing, or pressing Cancel stops the active task. Late updates cannot activate themselves in another context.

Download task group

The coordinator uses a task group and a small loop state:

  • nextIndex identifies unscheduled work;
  • runningCount tracks child tasks;
  • records contain completed outcomes;
  • scheduling fills available concurrency slots;
  • pause prevents new scheduling;
  • cancel stops scheduling and cancels active Telegram file IDs.

Progress callbacks cross back to AppModel on the main actor. The batch state can be Preparing, Downloading, Pausing, Paused, or Cancelling.

Error model

Infrastructure uses typed errors for conditions the UI can recover from:

  • TDLib invalid envelope, transport failure, remote error, closure;
  • destination unavailable, stale bookmark, not writable, unsafe filename, size mismatch, insufficient space;
  • Keychain status and invalid stored data;
  • chat-store unavailable, unreadable, or unwritable.

The presentation layer maps these errors to product copy. It does not expose raw authorization JSON, paths, or private Telegram payloads.

Failure containment

  • A chat-cache write failure does not authorize cross-chat state.
  • An attachment snapshot write failure does not discard the in-memory scan.
  • A history write failure keeps current records visible and presents a history error.
  • A pending-batch write failure reports that recovery could not be saved.
  • Placement failure removes the temporary file when possible.
  • A single file failure becomes a record and does not erase successful files.

Production safety conventions

Production code avoids force unwraps and try!. Optional runtime resources are resolved through guarded paths, and dependency injection makes failure cases testable without a live account.

Clone this wiki locally