Throw from session directories and only fatal error when making sense.

This commit is contained in:
Stefan Ceriu
2026-09-30 11:36:06 +03:00
parent a8bc26dc93
commit 7973da8251
5 changed files with 21 additions and 12 deletions
@@ -280,7 +280,7 @@ class AuthenticationService: AuthenticationServiceProtocol {
} }
private func rotateSessionDirectory() { private func rotateSessionDirectory() {
sessionDirectories.delete() try? sessionDirectories.delete()
sessionDirectories = .init() sessionDirectories = .init()
} }
@@ -23,37 +23,42 @@ nonisolated struct SessionDirectories: Hashable, Codable {
// MARK: Data Management // MARK: Data Management
/// Removes the directories from disk if they have been created. /// Removes the directories from disk if they have been created.
func delete() { func delete() throws {
do { do {
if FileManager.default.directoryExists(at: dataDirectory) { if FileManager.default.directoryExists(at: dataDirectory) {
try FileManager.default.removeItem(at: dataDirectory) try FileManager.default.removeItem(at: dataDirectory)
} }
} catch { } catch {
MXLog.failure("Failed deleting the session data: \(error)") MXLog.error("Failed deleting the session data: \(error)")
throw error
} }
do { do {
if FileManager.default.directoryExists(at: cacheDirectory) { if FileManager.default.directoryExists(at: cacheDirectory) {
try FileManager.default.removeItem(at: cacheDirectory) try FileManager.default.removeItem(at: cacheDirectory)
} }
} catch { } catch {
MXLog.failure("Failed deleting the session caches: \(error)") MXLog.error("Failed deleting the session caches: \(error)")
throw error
} }
} }
/// Deletes the Rust state store and event cache data, leaving the crypto store and both /// Deletes the Rust state store and event cache data, leaving the crypto store and both
/// session directories in place along with any other data that may have been written in them. /// session directories in place along with any other data that may have been written in them.
func deleteTransientUserData() { func deleteTransientUserData() throws {
do { do {
let prefix = "matrix-sdk-state" let prefix = "matrix-sdk-state"
try deleteFiles(at: dataDirectory, with: prefix) try deleteFiles(at: dataDirectory, with: prefix)
} catch { } catch {
MXLog.failure("Failed clearing state store: \(error)") MXLog.failure("Failed clearing state store: \(error)")
throw error
} }
do { do {
let prefix = "matrix-sdk-event-cache" let prefix = "matrix-sdk-event-cache"
try deleteFiles(at: cacheDirectory, with: prefix) try deleteFiles(at: cacheDirectory, with: prefix)
} catch { } catch {
MXLog.failure("Failed clearing event cache store: \(error)") MXLog.failure("Failed clearing event cache store: \(error)")
throw error
} }
} }
@@ -69,7 +69,11 @@ class UserSessionStore: UserSessionStoreProtocol {
// On any restoration failure reset the token and restart // On any restoration failure reset the token and restart
keychainController.removeRestorationTokenForUsername(credentials.userID) keychainController.removeRestorationTokenForUsername(credentials.userID)
credentials.restorationToken.sessionDirectories.delete() do {
try credentials.restorationToken.sessionDirectories.delete()
} catch {
fatalError("Failed deleting session directories with error \(error)")
}
return .failure(error) return .failure(error)
} }
@@ -103,7 +107,7 @@ class UserSessionStore: UserSessionStoreProtocol {
keychainController.removeRestorationTokenForUsername(userID) keychainController.removeRestorationTokenForUsername(userID)
if let credentials { if let credentials {
credentials.restorationToken.sessionDirectories.delete() try? credentials.restorationToken.sessionDirectories.delete()
} }
} }
@@ -55,7 +55,7 @@ struct SessionDirectoriesTests {
#expect(fileManager.directoryExists(at: sessionDirectories.cacheDirectory)) #expect(fileManager.directoryExists(at: sessionDirectories.cacheDirectory))
// When deleting the directories. // When deleting the directories.
sessionDirectories.delete() try? sessionDirectories.delete()
// Then neither directory should exist on disk. // Then neither directory should exist on disk.
#expect(!fileManager.directoryExists(at: sessionDirectories.dataDirectory)) #expect(!fileManager.directoryExists(at: sessionDirectories.dataDirectory))
@@ -79,7 +79,7 @@ struct SessionDirectoriesTests {
#expect(try fileManager.numberOfItems(at: sessionDirectories.cacheDirectory) == 3) #expect(try fileManager.numberOfItems(at: sessionDirectories.cacheDirectory) == 3)
// When deleting transient user data. // When deleting transient user data.
sessionDirectories.deleteTransientUserData() try? sessionDirectories.deleteTransientUserData()
// Then the data directory should only contain the crypto store and the cache directory should remain but be empty. // Then the data directory should only contain the crypto store and the cache directory should remain but be empty.
#expect(fileManager.directoryExists(at: sessionDirectories.dataDirectory)) #expect(fileManager.directoryExists(at: sessionDirectories.dataDirectory))
@@ -92,6 +92,6 @@ struct SessionDirectoriesTests {
#expect(!fileManager.fileExists(atPath: sessionDirectories.mockEventCachePath)) #expect(!fileManager.fileExists(atPath: sessionDirectories.mockEventCachePath))
// The tests are done, tidy up these useless directories 🧹 // The tests are done, tidy up these useless directories 🧹
sessionDirectories.delete() try? sessionDirectories.delete()
} }
} }
@@ -73,7 +73,7 @@ struct UserSessionStoreTests {
func restoreWhenClientCreationFails() async throws { func restoreWhenClientCreationFails() async throws {
// Given valid session data but a client factory that fails. // Given valid session data but a client factory that fails.
let sessionDirectories = try makeValidSessionDirectories() let sessionDirectories = try makeValidSessionDirectories()
defer { sessionDirectories.delete() } defer { try? sessionDirectories.delete() }
let credentials = makeCredentials(sessionDirectories: sessionDirectories) let credentials = makeCredentials(sessionDirectories: sessionDirectories)
keychainController.restorationTokensReturnValue = [credentials] keychainController.restorationTokensReturnValue = [credentials]
clientFactory.makeAppClientCredentialsClientSessionDelegateAppSettingsAppHooksThrowableError = TestError.generic clientFactory.makeAppClientCredentialsClientSessionDelegateAppSettingsAppHooksThrowableError = TestError.generic
@@ -92,7 +92,7 @@ struct UserSessionStoreTests {
func restoreSucceeds() async throws { func restoreSucceeds() async throws {
// Given valid session data and a client factory that returns a client. // Given valid session data and a client factory that returns a client.
let sessionDirectories = try makeValidSessionDirectories() let sessionDirectories = try makeValidSessionDirectories()
defer { sessionDirectories.delete() } defer { try? sessionDirectories.delete() }
keychainController.restorationTokensReturnValue = [makeCredentials(sessionDirectories: sessionDirectories)] keychainController.restorationTokensReturnValue = [makeCredentials(sessionDirectories: sessionDirectories)]
// When restoring the session. // When restoring the session.