Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide more flexible Account Service interactions #39

Merged
merged 27 commits into from
Aug 20, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
1dcddf9
First draft to upgrade to SpeziAccount 2.0
Supereg Jul 24, 2024
6c3a0f8
Reorder files
Supereg Jul 24, 2024
6f4a9a9
Tests compile
Supereg Jul 24, 2024
e907b70
Minor bump
Supereg Jul 24, 2024
c2c2908
Rewrite firestore account storage to new model
Supereg Jul 25, 2024
fc01d44
Minor changes
Supereg Jul 30, 2024
55c9a32
Update to latest version and make tests work
Supereg Aug 2, 2024
982d664
Merge branch 'main' into feature/spezi-account-2.0
Supereg Aug 2, 2024
78c7ae9
Update build command
Supereg Aug 2, 2024
09dd098
Update to latest SpeziAccount commit, supply user details within conf…
Supereg Aug 8, 2024
54526a1
Some concurrency fixes in the UITests
Supereg Aug 9, 2024
dbc6ce8
Complete documentation and todos
Supereg Aug 9, 2024
37fd7ad
Fix some issues
Supereg Aug 9, 2024
0d1d881
Minor fixes in tests
Supereg Aug 9, 2024
3dc47ec
Upgrade Firebase SDK and inherit isolation for setData methods
Supereg Aug 12, 2024
c834daf
Upgrade dependencies
Supereg Aug 13, 2024
9d50c68
Try with continatuions again for sendability
Supereg Aug 14, 2024
a19e42b
Minor adjustments
Supereg Aug 15, 2024
1505ea9
Make firebase data functions more safe
Supereg Aug 16, 2024
ddfe2bc
Restore projectid
Supereg Aug 16, 2024
e96ca97
Can we rerun?
Supereg Aug 16, 2024
0dd0cf8
Require latest beta
Supereg Aug 16, 2024
4195dd6
Rerun so Codecov might be able to report coverage this time?
Supereg Aug 16, 2024
d2fa896
Use new test extensions
Supereg Aug 19, 2024
8920a35
Fix compatibility
Supereg Aug 19, 2024
1ae1854
Versions
Supereg Aug 19, 2024
ce64630
Use latest beta to fix test focus issues
Supereg Aug 20, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,12 @@ let package = Package(
.library(name: "SpeziFirebaseAccountStorage", targets: ["SpeziFirebaseAccountStorage"])
],
dependencies: [
.package(url: "https://github.com/StanfordSpezi/SpeziFoundation.git", from: "2.0.0-beta.1"),
.package(url: "https://github.com/StanfordSpezi/SpeziFoundation", from: "2.0.0-beta.1"),
.package(url: "https://github.com/StanfordSpezi/Spezi", from: "1.7.1"),
.package(url: "https://github.com/StanfordSpezi/SpeziViews.git", from: "1.6.0"),
.package(url: "https://github.com/StanfordSpezi/SpeziViews", from: "1.6.0"),
.package(url: "https://github.com/StanfordSpezi/SpeziAccount", from: "2.0.0-beta.2"),
.package(url: "https://github.com/firebase/firebase-ios-sdk", from: "11.0.0")
.package(url: "https://github.com/firebase/firebase-ios-sdk", from: "11.0.0"),
.package(url: "https://github.com/apple/swift-atomics.git", from: "1.2.0")
] + swiftLintPackage(),
targets: [
.target(
Expand Down Expand Up @@ -71,7 +72,8 @@ let package = Package(
dependencies: [
.target(name: "SpeziFirebaseConfiguration"),
.product(name: "Spezi", package: "Spezi"),
.product(name: "FirebaseFirestore", package: "firebase-ios-sdk")
.product(name: "FirebaseFirestore", package: "firebase-ios-sdk"),
.product(name: "Atomics", package: "swift-atomics")
],
swiftSettings: [
swiftConcurrency
Expand Down Expand Up @@ -108,8 +110,7 @@ let package = Package(
dependencies: [
.target(name: "SpeziFirebaseAccount"),
.target(name: "SpeziFirebaseConfiguration"),
.target(name: "SpeziFirestore"),
.product(name: "XCTSpezi", package: "Spezi")
.target(name: "SpeziFirestore")
],
swiftSettings: [
swiftConcurrency
Expand Down
95 changes: 62 additions & 33 deletions Sources/SpeziFirestore/DocumentReference+AsyncAwait.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,61 @@
// SPDX-License-Identifier: MIT
//

import Atomics
import FirebaseFirestore
import Foundation
import OSLog


#if compiler(>=6)
private struct FirestoreCompletion: Sendable {
private static var logger: Logger {
Logger(subsystem: "edu.stanford.spezi.firebase", category: "FirestoreCompletion")
}

private let continuation: UnsafeContinuation<Void, Error>
private let resumed: ManagedAtomic<Bool>

private init(continuation: UnsafeContinuation<Void, Error>) {
self.continuation = continuation
self.resumed = ManagedAtomic(false)
}

static func perform(
isolation: isolated (any Actor)? = #isolation,
file: StaticString = #filePath,
line: Int = #line,
action: (FirestoreCompletion) throws -> Void
) async throws {
try await withUnsafeThrowingContinuation { continuation in
let completion = FirestoreCompletion(continuation: continuation)
do {
try action(completion)
} catch {
completion.complete(with: error, file: file, line: line)
}
}
}

func complete(
with error: Error?,
file: StaticString = #filePath,
line: Int = #line
) {
let (exchanged, _) = resumed.compareExchange(expected: false, desired: true, ordering: .relaxed)
if !exchanged {
Self.logger.warning("\(file):\(line): Firestore completion handler completed twice. This time with: \(error)")
return
}

if let error {
continuation.resume(throwing: FirestoreError(error))
} else {
continuation.resume()
}
}
}
#endif


extension DocumentReference {
Expand All @@ -31,17 +84,9 @@ extension DocumentReference {
from value: T,
encoder: FirebaseFirestore.Firestore.Encoder = FirebaseFirestore.Firestore.Encoder()
) async throws {
try await withCheckedThrowingContinuation { (continuation: CheckedContinuation<Void, Error>) in
do {
try setData(from: value, encoder: encoder) { error in
if let error {
continuation.resume(throwing: FirestoreError(error))
} else {
continuation.resume()
}
}
} catch {
continuation.resume(throwing: FirestoreError(error))
try await FirestoreCompletion.perform { completion in
try setData(from: value, encoder: encoder) { error in
completion.complete(with: error)
}
}
}
Expand Down Expand Up @@ -69,17 +114,9 @@ extension DocumentReference {
merge: Bool,
encoder: FirebaseFirestore.Firestore.Encoder = FirebaseFirestore.Firestore.Encoder()
) async throws {
try await withCheckedThrowingContinuation { (continuation: CheckedContinuation<Void, Error>) in
do {
try setData(from: value, merge: merge, encoder: encoder) { error in
if let error {
continuation.resume(throwing: FirestoreError(error))
} else {
continuation.resume()
}
}
} catch {
continuation.resume(throwing: FirestoreError(error))
try await FirestoreCompletion.perform { completion in
try setData(from: value, merge: merge, encoder: encoder) { error in
completion.complete(with: error)
}
}
}
Expand Down Expand Up @@ -111,17 +148,9 @@ extension DocumentReference {
mergeFields: [Any],
encoder: FirebaseFirestore.Firestore.Encoder = FirebaseFirestore.Firestore.Encoder()
) async throws {
try await withCheckedThrowingContinuation { (continuation: CheckedContinuation<Void, Error>) in
do {
try setData(from: value, mergeFields: mergeFields, encoder: encoder) { error in
if let error {
continuation.resume(throwing: FirestoreError(error))
} else {
continuation.resume()
}
}
} catch {
continuation.resume(throwing: FirestoreError(error))
try await FirestoreCompletion.perform { completion in
try setData(from: value, mergeFields: mergeFields, encoder: encoder) { error in
completion.complete(with: error)
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion Tests/UITests/TestAppUITests/FirebaseClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@


enum FirebaseClient {
private static let projectId = "spezifirebaseuitests"
private static let projectId = "nams-e43ed" // TODO: restore "spezifirebaseuitests"

Check failure on line 54 in Tests/UITests/TestAppUITests/FirebaseClient.swift

View workflow job for this annotation

GitHub Actions / SwiftLint / SwiftLint / SwiftLint

Todo Violation: TODOs should be resolved (restore "spezifirebaseuitests") (todo)
PSchmiedmayer marked this conversation as resolved.
Show resolved Hide resolved

// curl -H "Authorization: Bearer owner" -X DELETE http://localhost:9099/emulator/v1/projects/spezifirebaseuitests/accounts
static func deleteAllAccounts() async throws {
Expand Down Expand Up @@ -142,7 +142,7 @@
Firebase Local Emulator Suite.
"""
)
throw URLError(.fileDoesNotExist)

Check failure on line 145 in Tests/UITests/TestAppUITests/FirebaseClient.swift

View workflow job for this annotation

GitHub Actions / Build and Test UI Tests / Test using xcodebuild or run fastlane

testAccountLogout, failed: caught error: "Error Domain=NSURLErrorDomain Code=-1100 "(null)""

Check failure on line 145 in Tests/UITests/TestAppUITests/FirebaseClient.swift

View workflow job for this annotation

GitHub Actions / Build and Test UI Tests / Test using xcodebuild or run fastlane

testAccountRemoval, failed: caught error: "Error Domain=NSURLErrorDomain Code=-1100 "(null)""

Check failure on line 145 in Tests/UITests/TestAppUITests/FirebaseClient.swift

View workflow job for this annotation

GitHub Actions / Build and Test UI Tests / Test using xcodebuild or run fastlane

testInvalidCredentials, failed: caught error: "Error Domain=NSURLErrorDomain Code=-1100 "(null)""

Check failure on line 145 in Tests/UITests/TestAppUITests/FirebaseClient.swift

View workflow job for this annotation

GitHub Actions / Build and Test UI Tests / Test using xcodebuild or run fastlane

testPasswordChangeCancel, failed: caught error: "Error Domain=NSURLErrorDomain Code=-1100 "(null)""

Check failure on line 145 in Tests/UITests/TestAppUITests/FirebaseClient.swift

View workflow job for this annotation

GitHub Actions / Build and Test UI Tests / Test using xcodebuild or run fastlane

testPasswordChange, failed: caught error: "Error Domain=NSURLErrorDomain Code=-1100 "(null)""

Check failure on line 145 in Tests/UITests/TestAppUITests/FirebaseClient.swift

View workflow job for this annotation

GitHub Actions / Build and Test UI Tests / Test using xcodebuild or run fastlane

testPasswordChangeWrong, failed: caught error: "Error Domain=NSURLErrorDomain Code=-1100 "(null)""
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@
<CommandLineArguments>
<CommandLineArgument
argument = "--account-storage"
isEnabled = "NO">
isEnabled = "YES">
</CommandLineArgument>
</CommandLineArguments>
<LocationScenarioReference
Expand Down
Loading