リトライロジックとバックグラウンド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フィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- async/awaitによるURLSession data(from:)
- Codable:JSONのエンコードとデコード
- エラーハンドリングとHTTPステータスコード
- リトライロジックとバックグラウンドURLSession