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

[Core] Prefer completion handler APIs in Core Internal #13954

Merged
merged 1 commit into from
Oct 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Hide whitespace" makes this file easier to review.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Original file line number Diff line number Diff line change
Expand Up @@ -126,34 +126,30 @@ public final class HeartbeatController {
}
}

@available(iOS 13.0, macOS 10.15, macCatalyst 13.0, tvOS 13.0, watchOS 6.0, *)
public func flushAsync() async -> HeartbeatsPayload {
return await withCheckedContinuation { continuation in
let resetTransform = { (heartbeatsBundle: HeartbeatsBundle?) -> HeartbeatsBundle? in
guard let oldHeartbeatsBundle = heartbeatsBundle else {
return nil // Storage was empty.
}
// The new value that's stored will use the old's cache to prevent the
// logging of duplicates after flushing.
return HeartbeatsBundle(
capacity: self.heartbeatsStorageCapacity,
cache: oldHeartbeatsBundle.lastAddedHeartbeatDates
)
public func flushAsync(completionHandler: @escaping (HeartbeatsPayload) -> Void) {
let resetTransform = { (heartbeatsBundle: HeartbeatsBundle?) -> HeartbeatsBundle? in
guard let oldHeartbeatsBundle = heartbeatsBundle else {
return nil // Storage was empty.
}
// The new value that's stored will use the old's cache to prevent the
// logging of duplicates after flushing.
return HeartbeatsBundle(
capacity: self.heartbeatsStorageCapacity,
cache: oldHeartbeatsBundle.lastAddedHeartbeatDates
)
}

// Asynchronously gets and returns the stored heartbeats, resetting storage
// using the given transform.
storage.getAndSetAsync(using: resetTransform) { result in
switch result {
case let .success(heartbeatsBundle):
// If no heartbeats bundle was stored, return an empty payload.
continuation
.resume(returning: heartbeatsBundle?.makeHeartbeatsPayload() ?? HeartbeatsPayload
.emptyPayload)
case .failure:
// If the operation throws, assume no heartbeat(s) were retrieved or set.
continuation.resume(returning: HeartbeatsPayload.emptyPayload)
}
// Asynchronously gets and returns the stored heartbeats, resetting storage
// using the given transform.
storage.getAndSetAsync(using: resetTransform) { result in
switch result {
case let .success(heartbeatsBundle):
// If no heartbeats bundle was stored, return an empty payload.
completionHandler(heartbeatsBundle?.makeHeartbeatsPayload() ?? HeartbeatsPayload
.emptyPayload)
case .failure:
// If the operation throws, assume no heartbeat(s) were retrieved or set.
completionHandler(HeartbeatsPayload.emptyPayload)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,8 @@ public class _ObjC_HeartbeatController: NSObject {
public func flushAsync(completionHandler: @escaping (_ObjC_HeartbeatsPayload) -> Void) {
// TODO: When minimum version moves to iOS 13.0, restore the async version
// removed in #13952.
if #available(iOS 13.0, macOS 10.15, macCatalyst 13.0, tvOS 13.0, watchOS 6.0, *) {
Task {
let heartbeatsPayload = await heartbeatController.flushAsync()
completionHandler(_ObjC_HeartbeatsPayload(heartbeatsPayload))
}
} else {
// It is not expected to reach this state as this API should only be
// called on iOS 13.0+.
completionHandler(_ObjC_HeartbeatsPayload(HeartbeatsPayload.emptyPayload))
heartbeatController.flushAsync { heartbeatsPayload in
completionHandler(_ObjC_HeartbeatsPayload(heartbeatsPayload))
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,29 +52,36 @@ class HeartbeatLoggingIntegrationTests: XCTestCase {
)
}

@available(iOS 13.0, macOS 10.15, macCatalyst 13.0, tvOS 13.0, watchOS 6.0, *)
func testLogAndFlushAsync() async throws {
func testLogAndFlushAsync() throws {
// Given
let heartbeatController = HeartbeatController(id: #function)
let expectedDate = HeartbeatsPayload.dateFormatter.string(from: Date())
let expectation = self.expectation(description: #function)
// When
heartbeatController.log("dummy_agent")
let payload = await heartbeatController.flushAsync()
// Then
try HeartbeatLoggingTestUtils.assertEqualPayloadStrings(
payload.headerValue(),
"""
{
"version": 2,
"heartbeats": [
heartbeatController.flushAsync { payload in
// Then
do {
try HeartbeatLoggingTestUtils.assertEqualPayloadStrings(
payload.headerValue(),
"""
{
"agent": "dummy_agent",
"dates": ["\(expectedDate)"]
"version": 2,
"heartbeats": [
{
"agent": "dummy_agent",
"dates": ["\(expectedDate)"]
}
]
}
]
"""
)
expectation.fulfill()
} catch {
XCTFail("Unexpected error: \(error)")
}
"""
)
}
waitForExpectations(timeout: 1.0)
}

/// This test may flake if it is executed during the transition from one day to the next.
Expand Down
38 changes: 22 additions & 16 deletions FirebaseCore/Internal/Tests/Unit/HeartbeatControllerTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -58,35 +58,41 @@ class HeartbeatControllerTests: XCTestCase {
assertHeartbeatControllerFlushesEmptyPayload(controller)
}

@available(iOS 13.0, macOS 10.15, macCatalyst 13.0, tvOS 13.0, watchOS 6.0, *)
func testLogAndFlushAsync() async throws {
func testLogAndFlushAsync() throws {
// Given
let controller = HeartbeatController(
storage: HeartbeatStorageFake(),
dateProvider: { self.date }
)
let expectation = expectation(description: #function)

assertHeartbeatControllerFlushesEmptyPayload(controller)

// When
controller.log("dummy_agent")
let heartbeatPayload = await controller.flushAsync()

// Then
try HeartbeatLoggingTestUtils.assertEqualPayloadStrings(
heartbeatPayload.headerValue(),
"""
{
"version": 2,
"heartbeats": [
controller.flushAsync { heartbeatPayload in
// Then
do {
try HeartbeatLoggingTestUtils.assertEqualPayloadStrings(
heartbeatPayload.headerValue(),
"""
{
"agent": "dummy_agent",
"dates": ["2021-11-01"]
"version": 2,
"heartbeats": [
{
"agent": "dummy_agent",
"dates": ["2021-11-01"]
}
]
}
]
"""
)
expectation.fulfill()
} catch {
XCTFail("Unexpected error: \(error)")
}
"""
)
}
waitForExpectations(timeout: 1.0)

assertHeartbeatControllerFlushesEmptyPayload(controller)
}
Expand Down
Loading