Harden panic recovery and service shutdown

This commit is contained in:
jack
2026-07-26 00:12:26 +02:00
parent 76d3b0f1ed
commit b081c98dba
22 changed files with 1236 additions and 126 deletions
@@ -188,8 +188,25 @@ final class VoiceRecordingViewModel: ObservableObject {
Task {
let finalDuration = Date().timeIntervalSince(startDate)
if let url = await session.finish(),
isValidRecording(at: url, duration: finalDuration) {
if let url = await session.finish() {
// Panic and a newer hold both invalidate this completion.
// Never route an old recording using a post-panic target.
guard generation == holdGeneration else {
try? FileManager.default.removeItem(at: url)
return
}
guard isValidRecording(
at: url,
duration: finalDuration
) else {
guard state == .idle else { return }
state = .error(
message: finalDuration < VoiceRecorder.minRecordingDuration
? "Recording is too short."
: "Recording failed to save."
)
return
}
completion(url)
} else {
guard generation == holdGeneration, state == .idle else { return }
@@ -206,6 +223,17 @@ final class VoiceRecordingViewModel: ObservableObject {
finish(completion: nil)
}
/// Invalidates in-flight permission/start/finalize callbacks and tears
/// down an active microphone before the panic transaction continues.
func panicWipe() {
holdGeneration &+= 1
let session = activeSession
activeSession = nil
state = .idle
isLiveStreaming = false
session?.panicCancelSynchronously()
}
private func isValidRecording(at url: URL, duration: TimeInterval) -> Bool {
if let attributes = try? FileManager.default.attributesOfItem(atPath: url.path),
let fileSize = attributes[.size] as? NSNumber,