Skip to content

Commit 220f86f

Browse files
authored
Ensure the last element of reduction in the throttle is emitted and use appropriate delay (apple#292)
1 parent c889832 commit 220f86f

File tree

2 files changed

+30
-3
lines changed

2 files changed

+30
-3
lines changed

Sources/AsyncAlgorithms/AsyncThrottleSequence.swift

+10-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,16 @@ extension AsyncThrottleSequence: AsyncSequence {
8181
let start = last ?? clock.now
8282
repeat {
8383
guard let element = try await base.next() else {
84-
return nil
84+
if reduced != nil, let last {
85+
// ensure the rate of elements never exceeds the given interval
86+
let amount = interval - last.duration(to: clock.now)
87+
if amount > .zero {
88+
try? await clock.sleep(for: amount)
89+
}
90+
}
91+
// the last value is unable to have any subsequent
92+
// values so always return the last reduction
93+
return reduced
8594
}
8695
let reduction = await reducing(reduced, element)
8796
let now = clock.now

Tests/AsyncAlgorithmsTests/TestThrottle.swift

+20-2
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ final class TestThrottle: XCTestCase {
7272
validate {
7373
"abcdefghijk|"
7474
$0.inputs[0].throttle(for: .steps(3), clock: $0.clock)
75-
"a--d--g--j-|"
75+
"a--d--g--j--[k|]"
7676
}
7777
}
7878

@@ -81,7 +81,7 @@ final class TestThrottle: XCTestCase {
8181
validate {
8282
"abcdefghijk|"
8383
$0.inputs[0].throttle(for: .steps(3), clock: $0.clock, latest: false)
84-
"a--b--e--h-|"
84+
"a--b--e--h--[k|]"
8585
}
8686
}
8787

@@ -138,4 +138,22 @@ final class TestThrottle: XCTestCase {
138138
"-a---c---e---g---i---k-|"
139139
}
140140
}
141+
142+
func test_trailing_delay_without_latest() throws {
143+
guard #available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) else { throw XCTSkip("Skipped due to Clock/Instant/Duration availability") }
144+
validate {
145+
"abcdefghijkl|"
146+
$0.inputs[0].throttle(for: .steps(3), clock: $0.clock, latest: false)
147+
"a--b--e--h--[k|]"
148+
}
149+
}
150+
151+
func test_trailing_delay_with_latest() throws {
152+
guard #available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) else { throw XCTSkip("Skipped due to Clock/Instant/Duration availability") }
153+
validate {
154+
"abcdefghijkl|"
155+
$0.inputs[0].throttle(for: .steps(3), clock: $0.clock, latest: true)
156+
"a--d--g--j--[l|]"
157+
}
158+
}
141159
}

0 commit comments

Comments
 (0)