Skip to content

Commit ee78097

Browse files
authored
Use Swift's time types (#962)
* Use Swift's time types Resolves #955 * Formatting * Fix samples * Make Duration extensions internal; remove now() * Remove Deadline typealias
1 parent 9da657e commit ee78097

File tree

61 files changed

+374
-573
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+374
-573
lines changed

Samples/Sources/SampleDiningPhilosophers/DiningPhilosophers.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// This source file is part of the Swift Distributed Actors open source project
44
//
5-
// Copyright (c) 2018-2021 Apple Inc. and the Swift Distributed Actors project authors
5+
// Copyright (c) 2018-2022 Apple Inc. and the Swift Distributed Actors project authors
66
// Licensed under Apache License v2.0
77
//
88
// See LICENSE.txt for license information
@@ -18,7 +18,7 @@ final class DiningPhilosophers {
1818
private var forks: [Fork] = []
1919
private var philosophers: [Philosopher] = []
2020

21-
func run(for time: TimeAmount) async throws {
21+
func run(for duration: Duration) async throws {
2222
let system = await ClusterSystem("Philosophers")
2323

2424
// prepare 5 forks, the resources, that the philosophers will compete for:
@@ -38,6 +38,6 @@ final class DiningPhilosophers {
3838
Philosopher(name: "Erik", leftFork: fork4, rightFork: fork5, actorSystem: system),
3939
]
4040

41-
_Thread.sleep(time)
41+
_Thread.sleep(duration)
4242
}
4343
}

Samples/Sources/SampleDiningPhilosophers/DistributedDiningPhilosophers.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// This source file is part of the Swift Distributed Actors open source project
44
//
5-
// Copyright (c) 2018-2021 Apple Inc. and the Swift Distributed Actors project authors
5+
// Copyright (c) 2018-2022 Apple Inc. and the Swift Distributed Actors project authors
66
// Licensed under Apache License v2.0
77
//
88
// See LICENSE.txt for license information
@@ -18,7 +18,7 @@ final class DistributedDiningPhilosophers {
1818
private var forks: [Fork] = []
1919
private var philosophers: [Philosopher] = []
2020

21-
func run(for time: TimeAmount) async throws {
21+
func run(for duration: Duration) async throws {
2222
let systemA = await ClusterSystem("Node-A") { settings in
2323
settings.bindPort = 1111
2424
}
@@ -74,6 +74,6 @@ final class DistributedDiningPhilosophers {
7474
Philosopher(name: "Erik", leftFork: fork4, rightFork: fork5, actorSystem: systemC),
7575
]
7676

77-
try systemA.park(atMost: time)
77+
try systemA.park(atMost: duration)
7878
}
7979
}

Samples/Sources/SampleDiningPhilosophers/boot.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// This source file is part of the Swift Distributed Actors open source project
44
//
5-
// Copyright (c) 2018-2021 Apple Inc. and the Swift Distributed Actors project authors
5+
// Copyright (c) 2018-2022 Apple Inc. and the Swift Distributed Actors project authors
66
// Licensed under Apache License v2.0
77
//
88
// See LICENSE.txt for license information
@@ -40,13 +40,13 @@ typealias DefaultDistributedActorSystem = ClusterSystem
4040

4141
LoggingSystem.bootstrap(SamplePrettyLogHandler.init)
4242

43-
let time = TimeAmount.seconds(20)
43+
let duration = Duration.seconds(20)
4444

4545
switch CommandLine.arguments.dropFirst().first {
4646
case "dist", "distributed":
47-
try! await DistributedDiningPhilosophers().run(for: time)
47+
try! await DistributedDiningPhilosophers().run(for: duration)
4848
default:
49-
try! await DiningPhilosophers().run(for: time)
49+
try! await DiningPhilosophers().run(for: duration)
5050
}
5151
}
5252
}

Sources/DistributedActors/ActorContext.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ public class _ActorContext<Message: Codable> /* TODO(sendable): NOTSendable*/ {
234234
/// - continuation: continuation to run after `_AsyncResult` completes. It is safe to access
235235
/// and modify actor state from here.
236236
/// - Returns: a behavior that causes the actor to suspend until the `_AsyncResult` completes
237-
internal func awaitResult<AR: _AsyncResult>(of _AsyncResult: AR, timeout: TimeAmount, _ continuation: @escaping (Result<AR.Value, Error>) throws -> _Behavior<Message>) -> _Behavior<Message> {
237+
internal func awaitResult<AR: _AsyncResult>(of _AsyncResult: AR, timeout: Duration, _ continuation: @escaping (Result<AR.Value, Error>) throws -> _Behavior<Message>) -> _Behavior<Message> {
238238
_AsyncResult.withTimeout(after: timeout)._onComplete { [weak selfRef = self.myself._unsafeUnwrapCell] result in
239239
selfRef?.sendSystemMessage(.resume(result.map { $0 }))
240240
}
@@ -257,7 +257,7 @@ public class _ActorContext<Message: Codable> /* TODO(sendable): NOTSendable*/ {
257257
/// - Returns: a behavior that causes the actor to suspend until the `_AsyncResult` completes
258258
internal func awaitResultThrowing<AR: _AsyncResult>(
259259
of _AsyncResult: AR,
260-
timeout: TimeAmount,
260+
timeout: Duration,
261261
_ continuation: @escaping (AR.Value) throws -> _Behavior<Message>
262262
) -> _Behavior<Message> {
263263
self.awaitResult(of: _AsyncResult, timeout: timeout) { result in
@@ -280,7 +280,7 @@ public class _ActorContext<Message: Codable> /* TODO(sendable): NOTSendable*/ {
280280
/// - timeout: time after which the _AsyncResult will be failed if it does not complete
281281
/// - continuation: continuation to run after `_AsyncResult` completes.
282282
/// It is safe to access and modify actor state from here.
283-
internal func onResultAsync<AR: _AsyncResult>(of _AsyncResult: AR, timeout: TimeAmount, file: String = #file, line: UInt = #line, _ continuation: @escaping (Result<AR.Value, Error>) throws -> _Behavior<Message>) {
283+
internal func onResultAsync<AR: _AsyncResult>(of _AsyncResult: AR, timeout: Duration, file: String = #file, line: UInt = #line, _ continuation: @escaping (Result<AR.Value, Error>) throws -> _Behavior<Message>) {
284284
let asyncCallback = self.makeAsynchronousCallback(for: Result<AR.Value, Error>.self, file: file, line: line) {
285285
let nextBehavior = try continuation($0)
286286
let shell = self._downcastUnsafe
@@ -307,7 +307,7 @@ public class _ActorContext<Message: Codable> /* TODO(sendable): NOTSendable*/ {
307307
/// - timeout: time after which the _AsyncResult will be failed if it does not complete
308308
/// - continuation: continuation to run after `_AsyncResult` completes. It is safe to access
309309
/// and modify actor state from here.
310-
internal func onResultAsyncThrowing<AR: _AsyncResult>(of _AsyncResult: AR, timeout: TimeAmount, _ continuation: @escaping (AR.Value) throws -> _Behavior<Message>) {
310+
internal func onResultAsyncThrowing<AR: _AsyncResult>(of _AsyncResult: AR, timeout: Duration, _ continuation: @escaping (AR.Value) throws -> _Behavior<Message>) {
311311
self.onResultAsync(of: _AsyncResult, timeout: timeout) { res in
312312
switch res {
313313
case .success(let value): return try continuation(value)

Sources/DistributedActors/ActorRef+Ask.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ protocol ReceivesQuestions: Codable {
5252
/// It may be executed concurrently with regards to the current context.
5353
func ask<Answer>(
5454
for type: Answer.Type,
55-
timeout: TimeAmount,
55+
timeout: Duration,
5656
file: String, function: String, line: UInt,
5757
_ makeQuestion: @escaping (_ActorRef<Answer>) -> Question
5858
) -> AskResponse<Answer>
@@ -66,7 +66,7 @@ extension _ActorRef: ReceivesQuestions {
6666

6767
func ask<Answer>(
6868
for answerType: Answer.Type = Answer.self,
69-
timeout: TimeAmount,
69+
timeout: Duration,
7070
file: String = #file, function: String = #function, line: UInt = #line,
7171
_ makeQuestion: @escaping (_ActorRef<Answer>) -> Question
7272
) -> AskResponse<Answer> {
@@ -170,7 +170,7 @@ extension AskResponse: _AsyncResult {
170170
}
171171
}
172172

173-
func withTimeout(after timeout: TimeAmount) -> AskResponse<Value> {
173+
func withTimeout(after timeout: Duration) -> AskResponse<Value> {
174174
if timeout.isEffectivelyInfinite {
175175
return self
176176
}
@@ -245,7 +245,7 @@ internal enum AskActor {
245245
static func behavior<Message, ResponseType>(
246246
_ completable: EventLoopPromise<ResponseType>,
247247
ref: _ActorRef<Message>,
248-
timeout: TimeAmount,
248+
timeout: Duration,
249249
file: String,
250250
function: String,
251251
line: UInt

Sources/DistributedActors/AsyncResult.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// This source file is part of the Swift Distributed Actors open source project
44
//
5-
// Copyright (c) 2018-2019 Apple Inc. and the Swift Distributed Actors project authors
5+
// Copyright (c) 2018-2022 Apple Inc. and the Swift Distributed Actors project authors
66
// Licensed under Apache License v2.0
77
//
88
// See LICENSE.txt for license information
@@ -44,15 +44,15 @@ internal protocol _AsyncResult {
4444
/// value for the returned `_AsyncResult`.
4545
///
4646
/// - parameter after: defines a timeout after which the result should be considered failed.
47-
func withTimeout(after timeout: TimeAmount) -> Self
47+
func withTimeout(after timeout: Duration) -> Self
4848
}
4949

5050
extension EventLoopFuture: _AsyncResult {
5151
func _onComplete(_ callback: @escaping (Result<Value, Error>) -> Void) {
5252
self.whenComplete(callback)
5353
}
5454

55-
func withTimeout(after timeout: TimeAmount) -> EventLoopFuture<Value> {
55+
func withTimeout(after timeout: Duration) -> EventLoopFuture<Value> {
5656
if timeout == .effectivelyInfinite {
5757
return self
5858
}
@@ -73,9 +73,9 @@ extension EventLoopFuture: _AsyncResult {
7373
/// Error that signals that an operation timed out.
7474
internal struct TimeoutError: Error {
7575
let message: String
76-
let timeout: TimeAmount
76+
let timeout: Duration
7777

78-
init(message: String, timeout: TimeAmount) {
78+
init(message: String, timeout: Duration) {
7979
self.message = message
8080
self.timeout = timeout
8181
}

Sources/DistributedActors/Backoff.swift

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// This source file is part of the Swift Distributed Actors open source project
44
//
5-
// Copyright (c) 2018-2019 Apple Inc. and the Swift Distributed Actors project authors
5+
// Copyright (c) 2018-2022 Apple Inc. and the Swift Distributed Actors project authors
66
// Licensed under Apache License v2.0
77
//
88
// See LICENSE.txt for license information
@@ -22,7 +22,7 @@
2222
/// See also: `ConstantBackoffStrategy`, `ExponentialBackoffStrategy`
2323
public protocol BackoffStrategy {
2424
/// Returns next backoff interval to use OR `nil` if no further retries should be performed.
25-
mutating func next() -> TimeAmount?
25+
mutating func next() -> Duration?
2626

2727
/// Reset the strategy to its initial backoff amount.
2828
mutating func reset()
@@ -46,8 +46,8 @@ public enum Backoff {
4646
/// Backoff each time using the same, constant, time amount.
4747
///
4848
/// See `ConstantBackoffStrategy` for details
49-
public static func constant(_ backoff: TimeAmount) -> ConstantBackoffStrategy {
50-
.init(timeAmount: backoff)
49+
public static func constant(_ backoff: Duration) -> ConstantBackoffStrategy {
50+
.init(duration: backoff)
5151
}
5252

5353
/// Creates a strategy implementing the exponential backoff pattern.
@@ -68,9 +68,9 @@ public enum Backoff {
6868
/// - maxAttempts: An optional maximum number of times backoffs shall be attempted.
6969
/// MUST be `> 0` if set (or `nil`).
7070
public static func exponential(
71-
initialInterval: TimeAmount = ExponentialBackoffStrategy.Defaults.initialInterval,
71+
initialInterval: Duration = ExponentialBackoffStrategy.Defaults.initialInterval,
7272
multiplier: Double = ExponentialBackoffStrategy.Defaults.multiplier,
73-
capInterval: TimeAmount = ExponentialBackoffStrategy.Defaults.capInterval,
73+
capInterval: Duration = ExponentialBackoffStrategy.Defaults.capInterval,
7474
randomFactor: Double = ExponentialBackoffStrategy.Defaults.randomFactor,
7575
maxAttempts: Int? = ExponentialBackoffStrategy.Defaults.maxAttempts
7676
) -> ExponentialBackoffStrategy {
@@ -94,14 +94,14 @@ public enum Backoff {
9494
/// - SeeAlso: Also used to configure `_SupervisionStrategy`.
9595
public struct ConstantBackoffStrategy: BackoffStrategy {
9696
/// The constant time amount to back-off by each time.
97-
internal let timeAmount: TimeAmount
97+
internal let duration: Duration
9898

99-
public init(timeAmount: TimeAmount) {
100-
self.timeAmount = timeAmount
99+
public init(duration: Duration) {
100+
self.duration = duration
101101
}
102102

103-
public func next() -> TimeAmount? {
104-
self.timeAmount
103+
public func next() -> Duration? {
104+
self.duration
105105
}
106106

107107
public func reset() {
@@ -150,28 +150,28 @@ public struct ExponentialBackoffStrategy: BackoffStrategy {
150150

151151
/// Default values for the backoff parameters.
152152
public enum Defaults {
153-
public static let initialInterval: TimeAmount = .milliseconds(200)
153+
public static let initialInterval: Duration = .milliseconds(200)
154154
public static let multiplier: Double = 1.5
155-
public static let capInterval: TimeAmount = .effectivelyInfinite
155+
public static let capInterval: Duration = .effectivelyInfinite
156156
public static let randomFactor: Double = 0.25
157157

158158
// TODO: We could also implement taking a Clock, and using it see if there's a total limit exceeded
159-
// public static let maxElapsedTime: TimeAmount = .minutes(30)
159+
// public static let maxElapsedTime: Duration = .minutes(30)
160160

161161
public static let maxAttempts: Int? = nil
162162
}
163163

164-
let initialInterval: TimeAmount
164+
let initialInterval: Duration
165165
let multiplier: Double
166-
let capInterval: TimeAmount
166+
let capInterval: Duration
167167
let randomFactor: Double
168168

169169
var limitedRemainingAttempts: Int?
170170

171171
// interval that will be used in the `next()` call, does NOT include the random noise component
172-
private var currentBaseInterval: TimeAmount
172+
private var currentBaseInterval: Duration
173173

174-
internal init(initialInterval: TimeAmount, multiplier: Double, capInterval: TimeAmount, randomFactor: Double, maxAttempts: Int?) {
174+
internal init(initialInterval: Duration, multiplier: Double, capInterval: Duration, randomFactor: Double, maxAttempts: Int?) {
175175
precondition(initialInterval.nanoseconds > 0, "initialInterval MUST be > 0ns, was: [\(initialInterval.prettyDescription)]")
176176
precondition(multiplier >= 1.0, "multiplier MUST be >= 1.0, was: [\(multiplier)]")
177177
precondition(initialInterval <= capInterval, "capInterval MUST be >= initialInterval, was: [\(capInterval)]")
@@ -188,7 +188,7 @@ public struct ExponentialBackoffStrategy: BackoffStrategy {
188188
self.limitedRemainingAttempts = maxAttempts
189189
}
190190

191-
public mutating func next() -> TimeAmount? {
191+
public mutating func next() -> Duration? {
192192
defer { self.limitedRemainingAttempts? -= 1 }
193193
if let remainingAttempts = self.limitedRemainingAttempts, remainingAttempts <= 0 {
194194
return nil
@@ -226,5 +226,5 @@ public struct ExponentialBackoffStrategy: BackoffStrategy {
226226
// MARK: Errors
227227

228228
enum BackoffError {
229-
case exceededNumberOfAttempts(limit: Int, period: TimeAmount)
229+
case exceededNumberOfAttempts(limit: Int, period: Duration)
230230
}

Sources/DistributedActors/Cluster/Association.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -250,17 +250,17 @@ extension Association {
250250

251251
/// Determines when the Tombstone should be removed from kept tombstones in the ClusterShell.
252252
/// End of life of the tombstone is calculated as `now + settings.associationTombstoneTTL`.
253-
let removalDeadline: Deadline
253+
let removalDeadline: ContinuousClock.Instant
254254

255255
init(_ node: UniqueNode, settings: ClusterSystemSettings) {
256256
// TODO: if we made system carry system.time we could always count from that point in time with a TimeAmount; require Clock and settings then
257-
self.removalDeadline = Deadline.fromNow(settings.associationTombstoneTTL)
257+
self.removalDeadline = .fromNow(settings.associationTombstoneTTL)
258258
self.remoteNode = node
259259
}
260260

261261
/// Used to create "any" tombstone, for being able to lookup in Set<TombstoneSet>
262262
init(_ node: UniqueNode) {
263-
self.removalDeadline = Deadline.uptimeNanoseconds(1) // ANY value here is ok, we do not use it in hash/equals
263+
self.removalDeadline = .now // ANY value here is ok, we do not use it in hash/equals
264264
self.remoteNode = node
265265
}
266266

Sources/DistributedActors/Cluster/Downing/DowningSettings.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ public enum OnDownActionStrategySettings {
4242
/// members MUST refuse communication with this down node.
4343
case none
4444
/// Upon noticing that this member is marked as [.down], initiate a shutdown.
45-
case gracefulShutdown(delay: TimeAmount)
45+
case gracefulShutdown(delay: Duration)
4646

4747
func make() -> (ClusterSystem) throws -> Void {
4848
switch self {

Sources/DistributedActors/Cluster/Downing/DowningStrategy.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public struct DowningStrategyDirective {
3535
internal enum Repr {
3636
case none
3737
case markAsDown(Set<Cluster.Member>)
38-
case startTimer(key: TimerKey, member: Cluster.Member, delay: TimeAmount)
38+
case startTimer(key: TimerKey, member: Cluster.Member, delay: Duration)
3939
case cancelTimer(key: TimerKey)
4040
}
4141

@@ -47,7 +47,7 @@ public struct DowningStrategyDirective {
4747
.init(.none)
4848
}
4949

50-
public static func startTimer(key: TimerKey, member: Cluster.Member, delay: TimeAmount) -> Self {
50+
public static func startTimer(key: TimerKey, member: Cluster.Member, delay: Duration) -> Self {
5151
.init(.startTimer(key: key, member: member, delay: delay))
5252
}
5353

0 commit comments

Comments
 (0)