diff --git a/SignalCoreKit/src/Promises/Guarantee+Race.swift b/SignalCoreKit/src/Promises/Guarantee+Race.swift new file mode 100644 index 0000000..bda4303 --- /dev/null +++ b/SignalCoreKit/src/Promises/Guarantee+Race.swift @@ -0,0 +1,31 @@ +// +// Copyright 2023 Signal Messenger, LLC +// SPDX-License-Identifier: AGPL-3.0-only +// + +import Foundation + +public extension Guarantee { + static func race( + on scheduler: Scheduler, + _ guarantees: Guarantee... + ) -> Guarantee { + return race(on: scheduler, guarantees) + } + + static func race( + on scheduler: Scheduler, + _ guarantees: [Guarantee] + ) -> Guarantee { + let (result, future) = Guarantee.pending() + + for guarantee in guarantees { + guarantee.done(on: scheduler) { result in + guard !future.isSealed else { return } + future.resolve(result) + } + } + + return result + } +} diff --git a/SignalCoreKit/src/Promises/Guarantee+Timeout.swift b/SignalCoreKit/src/Promises/Guarantee+Timeout.swift new file mode 100644 index 0000000..e4c41ad --- /dev/null +++ b/SignalCoreKit/src/Promises/Guarantee+Timeout.swift @@ -0,0 +1,27 @@ +// +// Copyright 2023 Signal Messenger, LLC +// SPDX-License-Identifier: AGPL-3.0-only +// + +import Foundation + +public extension Guarantee { + func nilTimeout( + on scheduler: Scheduler, + seconds: TimeInterval + ) -> Guarantee { + let withOptionalValue: Guarantee = self.map(on: scheduler) { $0 } + return withOptionalValue.timeout(on: scheduler, seconds: seconds, substituteValue: nil) + } + + func timeout( + on scheduler: Scheduler, + seconds: TimeInterval, + substituteValue: Value + ) -> Guarantee { + let substitute: Guarantee = Guarantee + .after(on: scheduler, seconds: seconds) + .map(on: scheduler) { substituteValue } + return Guarantee.race(on: scheduler, [self, substitute]) + } +}