Skip to content

Commit cc61b56

Browse files
committed
Avoid colliding failed-audio dump filenames
Include a short UUID token so two empty ONNX dumps in the same second keep both WAV files. Sanitize model path characters too.
1 parent 8874768 commit cc61b56

2 files changed

Lines changed: 41 additions & 2 deletions

File tree

Sources/VocaMac/Services/FailedAudioDump.swift

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,26 @@ enum FailedAudioDump {
2727
UserDefaults.standard.bool(forKey: preferenceKey)
2828
}
2929

30+
/// Build a dump filename that cannot collide within the same second.
31+
static func makeFilename(
32+
model: String,
33+
date: Date = Date(),
34+
uniqueID: String = UUID().uuidString
35+
) -> String {
36+
let stamp = ISO8601DateFormatter.dumpFormatter.string(from: date)
37+
let token = String(uniqueID.replacingOccurrences(of: "-", with: "").prefix(8))
38+
let safeModel = model
39+
.replacingOccurrences(of: "/", with: "-")
40+
.replacingOccurrences(of: ":", with: "-")
41+
return "\(stamp)-\(token)-\(safeModel).wav"
42+
}
43+
3044
/// Save `samples` if the user asked for dumps. Returns the file written.
3145
@discardableResult
3246
static func save(_ samples: [Float], model: String, sampleRate: Int = 16_000) -> URL? {
3347
guard isEnabled, !samples.isEmpty else { return nil }
3448

35-
let stamp = ISO8601DateFormatter.dumpFormatter.string(from: Date())
36-
let url = directory.appendingPathComponent("\(stamp)-\(model).wav")
49+
let url = directory.appendingPathComponent(makeFilename(model: model))
3750

3851
do {
3952
try FileManager.default.createDirectory(

Tests/VocaMacTests/FailedAudioDumpTests.swift

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,29 @@ final class FailedAudioDumpTests: XCTestCase {
2828
XCTAssertNil(FailedAudioDump.save([0.1, 0.2], model: "canary-180m-flash"))
2929
}
3030
}
31+
32+
func testDumpFilenamesDoNotCollideWithinTheSameSecond() {
33+
let date = Date(timeIntervalSince1970: 1_700_000_000)
34+
let left = FailedAudioDump.makeFilename(
35+
model: "canary-180m-flash", date: date, uniqueID: "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
36+
)
37+
let right = FailedAudioDump.makeFilename(
38+
model: "canary-180m-flash", date: date, uniqueID: "ffffffff-1111-2222-3333-444444444444"
39+
)
40+
XCTAssertNotEqual(left, right)
41+
XCTAssertTrue(left.hasSuffix("-canary-180m-flash.wav"))
42+
XCTAssertTrue(left.contains("aaaaaaaa"))
43+
XCTAssertTrue(right.contains("ffffffff"))
44+
}
45+
46+
func testDumpFilenameSanitizesModelPathCharacters() {
47+
let name = FailedAudioDump.makeFilename(
48+
model: "path/with:chars",
49+
date: Date(timeIntervalSince1970: 0),
50+
uniqueID: "12345678-0000-0000-0000-000000000000"
51+
)
52+
XCTAssertFalse(name.contains("/"))
53+
XCTAssertFalse(name.contains(":"))
54+
XCTAssertTrue(name.hasSuffix("-path-with-chars.wav"))
55+
}
56+

0 commit comments

Comments
 (0)