Skip to content

Instantly share code, notes, and snippets.

@moyerr
Created October 3, 2024 19:10
Show Gist options
  • Save moyerr/002712404a42fc3b7778219e3472dc43 to your computer and use it in GitHub Desktop.
Save moyerr/002712404a42fc3b7778219e3472dc43 to your computer and use it in GitHub Desktop.
An AsyncSequence that iterates at most once every `interval`
/// 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