Skip to content

Commit

Permalink
Make HeartbeatController also conform to Sendable
Browse files Browse the repository at this point in the history
  • Loading branch information
ncooke3 committed Oct 28, 2024
1 parent 4eb6a37 commit 36d81b5
Show file tree
Hide file tree
Showing 3 changed files with 13 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
import Foundation

/// An object that provides API to log and flush heartbeats from a synchronized storage container.
public final class HeartbeatController {
public final class HeartbeatController: Sendable {
/// Used for standardizing dates for calendar-day comparison.
private enum DateStandardizer {
private static let calendar: Calendar = {
Expand All @@ -31,11 +31,11 @@ public final class HeartbeatController {
}

/// The thread-safe storage object to log and flush heartbeats from.
private let storage: HeartbeatStorageProtocol
private let storage: any HeartbeatStorageProtocol
/// The max capacity of heartbeats to store in storage.
private let heartbeatsStorageCapacity: Int = 30
private static let heartbeatsStorageCapacity: Int = 30
/// Current date provider. It is used for testability.
private let dateProvider: () -> Date
private let dateProvider: @Sendable () -> Date
/// Used for standardizing dates for calendar-day comparison.
private static let dateStandardizer = DateStandardizer.self

Expand All @@ -51,7 +51,7 @@ public final class HeartbeatController {
/// - Parameters:
/// - id: The id to associate this controller's heartbeat storage with.
/// - dateProvider: A date provider.
convenience init(id: String, dateProvider: @escaping () -> Date) {
convenience init(id: String, dateProvider: @escaping @Sendable () -> Date) {
let storage = HeartbeatStorage.getInstance(id: id)
self.init(storage: storage, dateProvider: dateProvider)
}
Expand All @@ -61,7 +61,7 @@ public final class HeartbeatController {
/// - storage: A heartbeat storage container.
/// - dateProvider: A date provider. Defaults to providing the current date.
init(storage: HeartbeatStorageProtocol,
dateProvider: @escaping () -> Date = Date.init) {
dateProvider: @escaping @Sendable () -> Date = Date.init) {
self.storage = storage
self.dateProvider = { Self.dateStandardizer.standardize(dateProvider()) }
}
Expand All @@ -76,7 +76,7 @@ public final class HeartbeatController {

storage.readAndWriteAsync { heartbeatsBundle in
var heartbeatsBundle = heartbeatsBundle ??
HeartbeatsBundle(capacity: self.heartbeatsStorageCapacity)
HeartbeatsBundle(capacity: Self.heartbeatsStorageCapacity)

// Filter for the time periods where the last heartbeat to be logged for
// that time period was logged more than one time period (i.e. day) ago.
Expand Down Expand Up @@ -109,7 +109,7 @@ public final class HeartbeatController {
// 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,
capacity: Self.heartbeatsStorageCapacity,
cache: oldHeartbeatsBundle.lastAddedHeartbeatDates
)
}
Expand All @@ -126,15 +126,15 @@ public final class HeartbeatController {
}
}

public func flushAsync(completionHandler: @escaping (HeartbeatsPayload) -> Void) {
let resetTransform = { (heartbeatsBundle: HeartbeatsBundle?) -> HeartbeatsBundle? in
public func flushAsync(completionHandler: @escaping @Sendable (HeartbeatsPayload) -> Void) {
let resetTransform = { @Sendable (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,
capacity: Self.heartbeatsStorageCapacity,
cache: oldHeartbeatsBundle.lastAddedHeartbeatDates
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
import Foundation

/// A type that can perform atomic operations using block-based transformations.
protocol HeartbeatStorageProtocol {
protocol HeartbeatStorageProtocol: Sendable {
func readAndWriteSync(using transform: (HeartbeatsBundle?) -> HeartbeatsBundle?)
func readAndWriteAsync(using transform: @escaping @Sendable (HeartbeatsBundle?)
-> HeartbeatsBundle?)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public class _ObjC_HeartbeatController: NSObject {
///
/// - Note: This API is thread-safe.
/// - Returns: A heartbeats payload for the flushed heartbeat(s).
public func flushAsync(completionHandler: @escaping (_ObjC_HeartbeatsPayload) -> Void) {
public func flushAsync(completionHandler: @escaping @Sendable (_ObjC_HeartbeatsPayload) -> Void) {
// TODO: When minimum version moves to iOS 13.0, restore the async version
// removed in #13952.
heartbeatController.flushAsync { heartbeatsPayload in
Expand Down

0 comments on commit 36d81b5

Please sign in to comment.