Created
October 3, 2024 19:10
-
-
Save moyerr/002712404a42fc3b7778219e3472dc43 to your computer and use it in GitHub Desktop.
An AsyncSequence that iterates at most once every `interval`
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// An AsyncSequence that iterates at most once every `interval` | |
public struct AsyncIntervalSequence<Base: AsyncSequence, C: Clock> { | |
public let base: Base | |
public let interval: C.Instant.Duration | |
public let clock: C | |
public init(_ base: Base, interval: C.Instant.Duration, clock: C) { | |
self.base = base | |
self.interval = interval | |
self.clock = clock | |
} | |
} | |
extension AsyncIntervalSequence: AsyncSequence { | |
public typealias Element = Base.Element | |
public struct AsyncIterator: AsyncIteratorProtocol { | |
public var base: Base.AsyncIterator | |
public let interval: C.Instant.Duration | |
public let clock: C | |
public var last: C.Instant? | |
public init(_ base: Base.AsyncIterator, interval: C.Instant.Duration, clock: C) { | |
self.base = base | |
self.interval = interval | |
self.clock = clock | |
} | |
public mutating func next() async throws -> Base.Element? { | |
if let last { | |
let next = last.advanced(by: interval) | |
if clock.now < next { | |
try await Task.sleep(until: next, clock: clock) | |
} | |
} | |
last = clock.now | |
return try await base.next() | |
} | |
} | |
public func makeAsyncIterator() -> AsyncIterator { | |
AsyncIterator(base.makeAsyncIterator(), interval: interval, clock: clock) | |
} | |
} | |
extension AsyncSequence { | |
public func every( | |
_ interval: Duration | |
) -> AsyncIntervalSequence<Self, ContinuousClock> { | |
.init(self, interval: interval, clock: .continuous) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment