diff --git a/Recap/Services/Processing/ProcessingCoordinator.swift b/Recap/Services/Processing/ProcessingCoordinator.swift index 4ad5461..6fd9bd9 100644 --- a/Recap/Services/Processing/ProcessingCoordinator.swift +++ b/Recap/Services/Processing/ProcessingCoordinator.swift @@ -59,9 +59,46 @@ final class ProcessingCoordinator: ProcessingCoordinatorType { func retryProcessing(recordingID: String) async { guard let recording = try? await recordingRepository.fetchRecording(id: recordingID), recording.canRetry else { return } - + await startProcessing(recordingInfo: recording) } + + func retrySummarization(recordingID: String) async { + guard let recording = try? await recordingRepository.fetchRecording(id: recordingID), + let transcriptionText = recording.transcriptionText, + !transcriptionText.isEmpty else { return } + + currentProcessingState = .processing(recordingID: recording.id) + delegate?.processingDidStart(recordingID: recording.id) + + processingTask = Task { + await resumeSummarization(recording, transcriptionText: transcriptionText) + } + + await processingTask?.value + currentProcessingState = .idle + } + + private func resumeSummarization(_ recording: RecordingInfo, transcriptionText: String) async { + let startTime = Date() + + do { + let summaryText = try await performSummarizationPhase(recording, transcriptionText: transcriptionText) + guard !Task.isCancelled else { throw ProcessingError.cancelled } + + await completeProcessing( + recording: recording, + transcriptionText: transcriptionText, + summaryText: summaryText, + startTime: startTime + ) + } catch let error as ProcessingError { + await handleProcessingError(error, for: recording) + } catch { + let processingError = ProcessingError.summarizationFailed(error.localizedDescription) + await handleProcessingError(processingError, for: recording) + } + } private func startQueueProcessing() { queueTask = Task { diff --git a/Recap/Services/Processing/ProcessingCoordinatorType.swift b/Recap/Services/Processing/ProcessingCoordinatorType.swift index ba93d02..a8eaf2d 100644 --- a/Recap/Services/Processing/ProcessingCoordinatorType.swift +++ b/Recap/Services/Processing/ProcessingCoordinatorType.swift @@ -14,6 +14,7 @@ protocol ProcessingCoordinatorType { func startProcessing(recordingInfo: RecordingInfo) async func cancelProcessing(recordingID: String) async func retryProcessing(recordingID: String) async + func retrySummarization(recordingID: String) async } @MainActor diff --git a/Recap/UseCases/Summary/ViewModel/SummaryViewModel.swift b/Recap/UseCases/Summary/ViewModel/SummaryViewModel.swift index 72ed8ae..5a4c86d 100644 --- a/Recap/UseCases/Summary/ViewModel/SummaryViewModel.swift +++ b/Recap/UseCases/Summary/ViewModel/SummaryViewModel.swift @@ -78,20 +78,13 @@ final class SummaryViewModel: SummaryViewModelType { func retryProcessing() async { guard let recording = currentRecording else { return } - + if recording.state == .transcriptionFailed { await processingCoordinator.retryProcessing(recordingID: recording.id) + } else if recording.state == .summarizationFailed || recording.state == .completed { + await processingCoordinator.retrySummarization(recordingID: recording.id) } else { - do { - try await recordingRepository.updateRecordingState( - id: recording.id, - state: .summarizing, - errorMessage: nil - ) - await processingCoordinator.startProcessing(recordingInfo: recording) - } catch { - errorMessage = "Failed to retry summarization: \(error.localizedDescription)" - } + await processingCoordinator.retryProcessing(recordingID: recording.id) } loadRecording(withID: recording.id) diff --git a/RecapTests/UseCases/Summary/ViewModels/SummaryViewModelSpec.swift b/RecapTests/UseCases/Summary/ViewModels/SummaryViewModelSpec.swift index 79c04af..c3a979a 100644 --- a/RecapTests/UseCases/Summary/ViewModels/SummaryViewModelSpec.swift +++ b/RecapTests/UseCases/Summary/ViewModels/SummaryViewModelSpec.swift @@ -110,21 +110,59 @@ final class SummaryViewModelSpec: XCTestCase { func testRetryProcessingForTranscriptionFailed() async throws { let recording = createTestRecording(id: "test-id", state: .transcriptionFailed) sut.currentRecording = recording - + given(mockProcessingCoordinator) .retryProcessing(recordingID: .any) .willReturn() - + given(mockRecordingRepository) .fetchRecording(id: .any) .willReturn(recording) - + await sut.retryProcessing() - + verify(mockProcessingCoordinator) .retryProcessing(recordingID: .any) .called(1) } + + func testRetryProcessingForSummarizationFailed() async throws { + let recording = createTestRecording(id: "test-id", state: .summarizationFailed) + sut.currentRecording = recording + + given(mockProcessingCoordinator) + .retrySummarization(recordingID: .any) + .willReturn() + + given(mockRecordingRepository) + .fetchRecording(id: .any) + .willReturn(recording) + + await sut.retryProcessing() + + verify(mockProcessingCoordinator) + .retrySummarization(recordingID: .any) + .called(1) + } + + func testRetryProcessingForCompletedCallsRetrySummarization() async throws { + let recording = createTestRecording(id: "test-id", state: .completed, summaryText: "Old summary") + sut.currentRecording = recording + + given(mockProcessingCoordinator) + .retrySummarization(recordingID: .any) + .willReturn() + + given(mockRecordingRepository) + .fetchRecording(id: .any) + .willReturn(recording) + + await sut.retryProcessing() + + verify(mockProcessingCoordinator) + .retrySummarization(recordingID: .any) + .called(1) + } func testCopySummaryShowsToast() async throws { let recording = createTestRecording(