Skip to content

Commit a4c12ae

Browse files
authored
Use appropriate storage location + migrate events (#399)
* Use proper directory for storage + migrate * Remove dead code. * tightened up migration code
1 parent 96380e2 commit a4c12ae

File tree

3 files changed

+81
-10
lines changed

3 files changed

+81
-10
lines changed

Sources/Segment/State.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,6 @@ struct System: State {
149149

150150
func reduce(state: System) -> System {
151151
var waitingPlugins = state.waitingPlugins
152-
let countBefore = waitingPlugins.count
153152
waitingPlugins.removeAll { p in
154153
return plugin === p
155154
}

Sources/Segment/Utilities/Utils.swift

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -75,17 +75,45 @@ extension Optional: Flattenable {
7575
}
7676

7777
internal func eventStorageDirectory(writeKey: String) -> URL {
78-
#if (os(iOS) || os(watchOS)) && !targetEnvironment(macCatalyst)
79-
let searchPathDirectory = FileManager.SearchPathDirectory.documentDirectory
80-
#else
81-
let searchPathDirectory = FileManager.SearchPathDirectory.cachesDirectory
82-
#endif
78+
let urls = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask)
79+
let appSupportURL = urls[0]
80+
let segmentURL = appSupportURL.appendingPathComponent("segment/\(writeKey)/")
81+
82+
// Handle one-time migration from old locations
83+
migrateFromOldLocations(writeKey: writeKey, to: segmentURL)
8384

84-
let urls = FileManager.default.urls(for: searchPathDirectory, in: .userDomainMask)
85-
let docURL = urls[0]
86-
let segmentURL = docURL.appendingPathComponent("segment/\(writeKey)/")
8785
// try to create it, will fail if already exists, nbd.
8886
// tvOS, watchOS regularly clear out data.
8987
try? FileManager.default.createDirectory(at: segmentURL, withIntermediateDirectories: true, attributes: nil)
9088
return segmentURL
9189
}
90+
91+
private func migrateFromOldLocations(writeKey: String, to newLocation: URL) {
92+
let fm = FileManager.default
93+
94+
// Get the parent of where our new segment directory should live
95+
let appSupportURL = fm.urls(for: .applicationSupportDirectory, in: .userDomainMask)[0]
96+
let newSegmentDir = appSupportURL.appendingPathComponent("segment")
97+
98+
// If segment dir already exists in app support, we're done
99+
guard !fm.fileExists(atPath: newSegmentDir.path) else { return }
100+
101+
// Only check the old location that was actually used on this platform
102+
#if (os(iOS) || os(watchOS)) && !targetEnvironment(macCatalyst)
103+
let oldSearchPath = FileManager.SearchPathDirectory.documentDirectory
104+
#else
105+
let oldSearchPath = FileManager.SearchPathDirectory.cachesDirectory
106+
#endif
107+
108+
guard let oldBaseURL = fm.urls(for: oldSearchPath, in: .userDomainMask).first else { return }
109+
let oldSegmentDir = oldBaseURL.appendingPathComponent("segment")
110+
111+
guard fm.fileExists(atPath: oldSegmentDir.path) else { return }
112+
113+
do {
114+
try fm.moveItem(at: oldSegmentDir, to: newSegmentDir)
115+
Analytics.segmentLog(message: "Migrated analytics data from \(oldSegmentDir.path)", kind: .debug)
116+
} catch {
117+
Analytics.segmentLog(message: "Failed to migrate from \(oldSegmentDir.path): \(error)", kind: .error)
118+
}
119+
}

Tests/Segment-Tests/Storage_Tests.swift

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,10 @@ class StorageTests: XCTestCase {
137137
}
138138

139139
func testFilePrepAndFinish() {
140-
let analytics = Analytics(configuration: Configuration(writeKey: "test"))
140+
let config = Configuration(writeKey: "test")
141+
.storageMode(.diskAtURL(URL(fileURLWithPath: NSTemporaryDirectory())))
142+
let analytics = Analytics(configuration: config)
143+
141144
analytics.storage.hardReset(doYouKnowHowToUseThis: true)
142145

143146
analytics.waitUntilStarted()
@@ -302,4 +305,45 @@ class StorageTests: XCTestCase {
302305
let remaining = analytics.storage.read(.events)
303306
XCTAssertNil(remaining)
304307
}
308+
309+
func testMigrationFromOldLocation() {
310+
let writeKey = "test-migration"
311+
let fm = FileManager.default
312+
313+
// Clean slate
314+
let appSupportURL = fm.urls(for: .applicationSupportDirectory, in: .userDomainMask)[0]
315+
let newSegmentDir = appSupportURL.appendingPathComponent("segment")
316+
try? fm.removeItem(at: newSegmentDir)
317+
318+
// Create fake old data in the platform-specific old location
319+
#if (os(iOS) || os(watchOS)) && !targetEnvironment(macCatalyst)
320+
let oldSearchPath = FileManager.SearchPathDirectory.documentDirectory
321+
#else
322+
let oldSearchPath = FileManager.SearchPathDirectory.cachesDirectory
323+
#endif
324+
325+
let oldBaseURL = fm.urls(for: oldSearchPath, in: .userDomainMask)[0]
326+
let oldSegmentDir = oldBaseURL.appendingPathComponent("segment/\(writeKey)")
327+
try! fm.createDirectory(at: oldSegmentDir, withIntermediateDirectories: true, attributes: nil)
328+
329+
// Write some fake event files
330+
let testFile1 = oldSegmentDir.appendingPathComponent("0-segment-events.temp")
331+
let testFile2 = oldSegmentDir.appendingPathComponent("1-segment-events.temp")
332+
try! "fake event data 1".write(to: testFile1, atomically: true, encoding: .utf8)
333+
try! "fake event data 2".write(to: testFile2, atomically: true, encoding: .utf8)
334+
335+
// Trigger migration
336+
let resultURL = eventStorageDirectory(writeKey: writeKey)
337+
338+
// Verify migration worked
339+
XCTAssertTrue(fm.fileExists(atPath: resultURL.path))
340+
XCTAssertTrue(fm.fileExists(atPath: resultURL.appendingPathComponent("0-segment-events.temp").path))
341+
XCTAssertTrue(fm.fileExists(atPath: resultURL.appendingPathComponent("1-segment-events.temp").path))
342+
343+
// Verify old directory is gone
344+
XCTAssertFalse(fm.fileExists(atPath: oldSegmentDir.path))
345+
346+
// Clean up
347+
try? fm.removeItem(at: newSegmentDir)
348+
}
305349
}

0 commit comments

Comments
 (0)