diff --git a/FirebaseCore/Extension/FIRHeartbeatLogger.h b/FirebaseCore/Extension/FIRHeartbeatLogger.h index 6314f504f13e..65793b3db759 100644 --- a/FirebaseCore/Extension/FIRHeartbeatLogger.h +++ b/FirebaseCore/Extension/FIRHeartbeatLogger.h @@ -68,13 +68,23 @@ NSString *_Nullable FIRHeaderValueFromHeartbeatsPayload(FIRHeartbeatsPayload *he - (void)log; #ifndef FIREBASE_BUILD_CMAKE -/// Flushes heartbeats from storage into a structured payload of heartbeats. +/// Synchronously flushes heartbeats from storage into a structured payload of heartbeats. /// /// This API is for clients using platform logging V2. /// /// @note This API is thread-safe. /// @return A payload of heartbeats. - (FIRHeartbeatsPayload *)flushHeartbeatsIntoPayload; + +/// Asynchronously flushes heartbeats from storage into a structured payload of heartbeats. +/// +/// This API is for clients using platform logging V2. +/// +/// @note This API is thread-safe. +/// @param completionHandler A completion handler to process the flushed payload of heartbeats. +- (void)flushHeartbeatsIntoPayloadWithCompletionHandler: + (void (^)(FIRHeartbeatsPayload *))completionHandler + API_AVAILABLE(ios(13.0), macosx(10.15), macCatalyst(13.0), tvos(13.0), watchos(6.0)); #endif // FIREBASE_BUILD_CMAKE /// Gets today's corresponding heartbeat code. diff --git a/FirebaseCore/Sources/FIRHeartbeatLogger.m b/FirebaseCore/Sources/FIRHeartbeatLogger.m index 08cd396a99e3..a5a2fcafe796 100644 --- a/FirebaseCore/Sources/FIRHeartbeatLogger.m +++ b/FirebaseCore/Sources/FIRHeartbeatLogger.m @@ -78,6 +78,13 @@ - (FIRHeartbeatsPayload *)flushHeartbeatsIntoPayload { FIRHeartbeatsPayload *payload = [_heartbeatController flush]; return payload; } + +- (void)flushHeartbeatsIntoPayloadWithCompletionHandler: + (void (^)(FIRHeartbeatsPayload *))completionHandler { + [_heartbeatController flushAsyncWithCompletionHandler:^(FIRHeartbeatsPayload *payload) { + completionHandler(payload); + }]; +} #endif // FIREBASE_BUILD_CMAKE - (FIRDailyHeartbeatCode)heartbeatCodeForToday { diff --git a/FirebaseCore/Tests/Unit/FIRHeartbeatLoggerTests.m b/FirebaseCore/Tests/Unit/FIRHeartbeatLoggerTests.m index 27c69c9fe207..93f3d2bc879f 100644 --- a/FirebaseCore/Tests/Unit/FIRHeartbeatLoggerTests.m +++ b/FirebaseCore/Tests/Unit/FIRHeartbeatLoggerTests.m @@ -125,6 +125,30 @@ - (void)testFlushing_UsingV2API_WhenHeartbeatsAreStored_ReturnsNonEmptyPayload { }]; } +- (void)testFlushingAsync_UsingV2API_WhenHeartbeatsAreStored_ReturnsNonEmptyPayload API_AVAILABLE( + ios(13.0), macosx(10.15), macCatalyst(13.0), tvos(13.0), watchos(6.0)) { + // Given + FIRHeartbeatLogger *heartbeatLogger = self.heartbeatLogger; + NSString *expectedDate = [[self class] formattedStringForDate:[NSDate date]]; + // When + [heartbeatLogger log]; + XCTestExpectation *expectation = [self expectationWithDescription:@"async flush"]; + [heartbeatLogger + flushHeartbeatsIntoPayloadWithCompletionHandler:^(FIRHeartbeatsPayload *heartbeatsPayload) { + // Then + [self assertEncodedPayloadHeader:FIRHeaderValueFromHeartbeatsPayload(heartbeatsPayload) + isEqualToPayloadJSON:@{ + @"version" : @2, + @"heartbeats" : @[ + @{@"agent" : @"dummy_agent", + @"dates" : @[ expectedDate ]} + ] + }]; + [expectation fulfill]; + }]; + [self waitForExpectations:@[ expectation ] timeout:1.0]; +} + - (void)testFlushing_UsingV2API_WhenNoHeartbeatsAreStored_ReturnsEmptyPayload { // Given FIRHeartbeatLogger *heartbeatLogger = self.heartbeatLogger; @@ -134,6 +158,21 @@ - (void)testFlushing_UsingV2API_WhenNoHeartbeatsAreStored_ReturnsEmptyPayload { [self assertHeartbeatsPayloadIsEmpty:heartbeatsPayload]; } +- (void)testFlushingAsync_UsingV2API_WhenNoHeartbeatsAreStored_ReturnsEmptyPayload API_AVAILABLE( + ios(13.0), macosx(10.15), macCatalyst(13.0), tvos(13.0), watchos(6.0)) { + // Given + FIRHeartbeatLogger *heartbeatLogger = self.heartbeatLogger; + // When + XCTestExpectation *expectation = [self expectationWithDescription:@"async flush"]; + [heartbeatLogger + flushHeartbeatsIntoPayloadWithCompletionHandler:^(FIRHeartbeatsPayload *heartbeatsPayload) { + // Then + [self assertHeartbeatsPayloadIsEmpty:heartbeatsPayload]; + [expectation fulfill]; + }]; + [self waitForExpectations:@[ expectation ] timeout:1.0]; +} + - (void)testLogAndFlushUsingV1API_AndThenFlushAgainUsingV2API_FlushesHeartbeatInTheFirstFlush { // Given FIRHeartbeatLogger *heartbeatLogger = self.heartbeatLogger;