Skip to content

Commit c405958

Browse files
committed
throttle
1 parent 2304c0d commit c405958

File tree

2 files changed

+37
-3
lines changed

2 files changed

+37
-3
lines changed

Coder-Desktop/VPNLib/Download.swift

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -129,9 +129,14 @@ public func download(
129129
src: URL,
130130
dest: URL,
131131
urlSession: URLSession,
132-
progressUpdates: ((DownloadProgress) -> Void)? = nil
132+
progressUpdates: (@Sendable (DownloadProgress) -> Void)? = nil
133133
) async throws(DownloadError) {
134-
try await DownloadManager().download(src: src, dest: dest, urlSession: urlSession, progressUpdates: progressUpdates)
134+
try await DownloadManager().download(
135+
src: src,
136+
dest: dest,
137+
urlSession: urlSession,
138+
progressUpdates: progressUpdates.flatMap { throttle(interval: .milliseconds(10), $0) },
139+
)
135140
}
136141

137142
func etag(data: Data) -> String {
@@ -173,7 +178,7 @@ private final class DownloadManager: NSObject, @unchecked Sendable {
173178
src: URL,
174179
dest: URL,
175180
urlSession: URLSession,
176-
progressUpdates: ((DownloadProgress) -> Void)?
181+
progressUpdates: (@Sendable (DownloadProgress) -> Void)?
177182
) async throws(DownloadError) {
178183
var req = URLRequest(url: src)
179184
if FileManager.default.fileExists(atPath: dest.path) {

Coder-Desktop/VPNLib/Util.swift

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,32 @@ public func makeNSError(suffix: String, code: Int = -1, desc: String) -> NSError
2929
userInfo: [NSLocalizedDescriptionKey: desc]
3030
)
3131
}
32+
33+
private actor Throttler<T: Sendable> {
34+
let interval: Duration
35+
let send: @Sendable (T) -> Void
36+
var lastFire: ContinuousClock.Instant?
37+
38+
init(interval: Duration, send: @escaping @Sendable (T) -> Void) {
39+
self.interval = interval
40+
self.send = send
41+
}
42+
43+
func push(_ value: T) {
44+
let now = ContinuousClock.now
45+
if let lastFire, now - lastFire < interval { return }
46+
lastFire = now
47+
send(value)
48+
}
49+
}
50+
51+
public func throttle<T: Sendable>(
52+
interval: Duration,
53+
_ send: @escaping @Sendable (T) -> Void
54+
) -> @Sendable (T) -> Void {
55+
let box = Throttler(interval: interval, send: send)
56+
57+
return { value in
58+
Task { await box.push(value) }
59+
}
60+
}

0 commit comments

Comments
 (0)