This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| private func retryAfterSeconds(from response: HTTPURLResponse) -> TimeInterval? { | |
| response.value(forHTTPHeaderField: "Retry-After").flatMap(TimeInterval.init) | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| private func makeChunkRequest(sessionId: String, offset: Int64, totalBytes: Int64) -> URLRequest { | |
| var request = URLRequest(url: url("level3/uploads/\(sessionId)/chunk")) | |
| request.httpMethod = "PUT" | |
| request.setValue("application/octet-stream", forHTTPHeaderField: "Content-Type") | |
| request.setValue("\(offset)", forHTTPHeaderField: "Upload-Offset") | |
| request.setValue("\(totalBytes)", forHTTPHeaderField: "Upload-Length") | |
| return request | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| private func makeIdempotencyKey(enabled: Bool) -> String? { | |
| guard enabled else { return nil } | |
| let key = UUID().uuidString | |
| return key | |
| } | |
| private func makePostRequest(text: String, idempotencyKey: String?) throws -> URLRequest { | |
| var request = makeRequest(path: "level2/tweets", method: "POST") | |
| request.setValue("application/json", forHTTPHeaderField: "Content-Type") | |
| if let idempotencyKey { |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| func retryAfterSeconds(from response: HTTPURLResponse) -> TimeInterval? { | |
| response.value(forHTTPHeaderField: "Retry-After").flatMap(TimeInterval.init) | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| func runExponentialBackoff(text: String) async throws { | |
| let maxAttempts = Constants.maxAttempts // 5 | |
| for attempt in 1...maxAttempts { | |
| do { | |
| _ = try await performOneAttempt(text: text) | |
| } catch Level2RetryFailure.transient(let message) { | |
| guard attempt < maxAttempts else { | |
| throw TweetUploadError.uploadFailed("Backoff retries exhausted after \(maxAttempts) attempts.") | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| func sendWithCircuitBreaker() async throws { | |
| if let openUntil = circuitOpenUntil, | |
| openUntil > Date() { | |
| throw UploadError.circuitOpen | |
| } | |
| do { | |
| try await sendOnce(); | |
| failures = 0 | |
| } catch { |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| func runExponentialBackoff(text: String) async throws { | |
| let maxAttempts = Constants.maxAttempts // 5 | |
| for attempt in 1...maxAttempts { | |
| do { | |
| _ = try await performOneAttempt(text: text) | |
| } catch Level2RetryFailure.transient(let message) { | |
| guard attempt < maxAttempts else { | |
| throw TweetUploadError.uploadFailed("Backoff retries exhausted after \(maxAttempts) attempts.") | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| func post(maxRetries: Int, attempt: Int = 0) async throws { | |
| do { try await URLSession.shared.data(for: request) } | |
| catch { | |
| guard attempt < maxRetries else { throw error } | |
| try await post(maxRetries: maxRetries, attempt: attempt + 1) | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| func sendOneShotTweet(text: String) async throws { | |
| var request = URLRequest(url: baseURL.appending(path: "level1/tweets")) | |
| request.httpMethod = "POST" | |
| request.setValue("application/json", forHTTPHeaderField: "Content-Type") | |
| request.httpBody = try encoder.encode(Level1PostBody(text: text)) | |
| _ = try await session.data(for: request) | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| @main | |
| struct FakeTwitterApp: App { | |
| @UIApplicationDelegateAdaptor(FakeTwitterAppDelegate.self) private var appDelegate | |
| private let modelContainer: ModelContainer | |
| private let level4Engine: UploadJobEngine | |
| init() { | |
| let schema = Schema([PersistedUploadJob.self]) | |
| let configuration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: false) |