0Pricing
Swift Academy · レッスン

リトライロジックとバックグラウンドURLSession

指数バックオフを実装し、バックグラウンドでダウンロードを継続します。

「リトライロジックとバックグラウンドURLSession」はCoddyKit上の無料Swift Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはSwift Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Swift Academyコースには全4レッスンが含まれています。

再試行する理由

一時的な失敗(タイムアウトや 503 Service Unavailable など)は回復できる可能性があります。再試行ロジックにより、ユーザーの操作なしで耐障害性を高められます。

func fetch(retries: Int = 3) async throws -> Data {
  for attempt in 0..<retries {
    do {
      return try await URLSession.shared.data(from: url).0
    } catch {
      if attempt == retries - 1 { throw error }
    }
  }
  fatalError("unreachable")
}

指数バックオフ

再試行の間隔を徐々に長くして、負荷が高まっているサーバーへの過剰なリクエストを防ぎます。例として 1 秒、2 秒、4 秒のように設定します。

for attempt in 0..<maxRetries {
  do { return try await fetch() } catch {
    if attempt < maxRetries - 1 {
      try await Task.sleep(nanoseconds: UInt64(pow(2.0, Double(attempt))) * 1_000_000_000)
    } else { throw error }
  }
}

Thundering Herd を防ぐジッター

バックオフの待機時間にランダムなジッターを加え、再試行するクライアントが同時にサーバーへアクセスしないようにします。

let baseDelay = pow(2.0, Double(attempt))
let jitter = Double.random(in: 0..<1)
let delay = (baseDelay + jitter) * 1_000_000_000
try await Task.sleep(nanoseconds: UInt64(delay))

再試行可能なエラーと再試行不可能なエラー

再試行するのは一時的なエラーだけにします。401 や 400 などのクライアントエラーは再試行してはいけません。

func isRetryable(_ error: Error) -> Bool {
  if let urlErr = error as? URLError {
    return urlErr.code == .timedOut || urlErr.code == .networkConnectionLost
  }
  if let netErr = error as? NetworkError, case .httpError(let code) = netErr {
    return code >= 500
  }
  return false
}

バックグラウンド URLSession

バックグラウンドセッションを使用すると、アプリが一時停止または終了された場合でもダウンロードを継続できます。

let config = URLSessionConfiguration.background(withIdentifier: "com.myapp.background")
let session = URLSession(configuration: config, delegate: self, delegateQueue: nil)

バックグラウンド用の URLSessionDelegate

URLSessionDelegate を実装すると、バックグラウンドタスクの完了後にアプリが再起動されたとき、完了コールバックを受け取れます。

func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
  let dest = documentsURL.appendingPathComponent("download.pdf")
  try? FileManager.default.moveItem(at: location, to: dest)
}

バックグラウンド App Refresh ハンドラー

AppDelegate でバックグラウンド完了ハンドラーを保存し、すべてのタスクが完了したときに呼び出します。

func application(_ app: UIApplication, handleEventsForBackgroundURLSession id: String, completionHandler: @escaping () -> Void) {
  backgroundCompletionHandler = completionHandler
}
func urlSessionDidFinishEvents(forBackgroundURLSession session: URLSession) {
  DispatchQueue.main.async { self.backgroundCompletionHandler?() }
}

バックグラウンドセッションでのダウンロードタスク

バックグラウンドセッションで downloadTask(with:) を使用すると、大きなファイルを堅牢にダウンロードできます。

let task = session.downloadTask(with: URL(string: "https://cdn.example.com/large.zip")!)
task.resume()

バックグラウンドでのアップロードタスク

バックグラウンドセッションでは、アプリが実行されていない場合でも継続するアップロードタスクもサポートされます。

var request = URLRequest(url: uploadURL)
request.httpMethod = "POST"
let task = session.uploadTask(with: request, fromFile: localFileURL)
task.resume()

進行状況の監視

URLSessionTaskDelegate を監視して、UI 更新用のアップロードやダウンロードの進行状況を追跡します。

func urlSession(_ session: URLSession, task: URLSessionTask, didSendBodyData bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64) {
  let progress = Double(totalBytesSent) / Double(totalBytesExpectedToSend)
  DispatchQueue.main.async { self.uploadProgress = progress }
}

再試行とバックグラウンド処理の組み合わせ

API 呼び出しにはフォアグラウンドでの再試行を使用し、長時間実行されるダウンロードやアップロードにはバックグラウンドセッションを使用します。

// API calls: async/await + exponential backoff retry
// Large downloads: URLSessionConfiguration.background + delegate

確認問題

再試行するクライアントがすべて同じ瞬間にサーバーへアクセスするのを防ぐ技法は何ですか。

レッスンのまとめ

一時的なエラーには、指数バックオフとジッターを組み合わせた再試行を実装します。再試行するのは 5xx エラーとタイムアウトエラーだけにします。アプリの一時停止後も継続する必要があるダウンロードやアップロードには、デリゲートとともに URLSessionConfiguration.background を使用します。

よくある質問

「リトライロジックとバックグラウンドURLSession」レッスンは無料ですか?

はい。「リトライロジックとバックグラウンドURLSession」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Swift Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Swift Academyコースには全4レッスンが含まれています。

「リトライロジックとバックグラウンドURLSession」で何を学びますか?

指数バックオフを実装し、バックグラウンドでダウンロードを継続します。 ブラウザで直接実行するハンズオンコードでSwift Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Swift Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのSwift Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。

「リトライロジックとバックグラウンドURLSession」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このSwift Academyレッスンでコードを書いて実行できますか?

はい。すべてのSwift Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. async/awaitによるURLSession data(from:)
  2. Codable:JSONのエンコードとデコード
  3. エラーハンドリングとHTTPステータスコード
  4. リトライロジックとバックグラウンドURLSession
← Swift Academyに戻る