I’ve implemented a simple rate limiting class in Swift. It’s based on a linked list and uses a DispatchSemaphore
for thread safety:
import Foundation
public class RateLimitter {
private class Node {
let time: Date
var nextNode: Node?
init(time: Date) {
self.time = time
}
}
private let dispatchSemaphore = DispatchSemaphore(value: 1)
private let limit: Int
private let timeInterval: TimeInterval
private var head: Node?
private var tail: Node?
private var count = 0
public init(limit: Int, per timeInterval: TimeInterval) {
if limit <= 0 {
fatalError("The RateLimitter's limit must be greater than 0")
}
if timeInterval <= 0 {
fatalError("The RateLimitter's time interval must be greater than 0")
}
self.limit = limit
self.timeInterval = timeInterval
}
public func beginOperation() -> Bool {
self.dispatchSemaphore.wait()
defer { self.dispatchSemaphore.signal() }
let threshold = Date().addingTimeInterval(-self.timeInterval)
while let head, head.time < threshold {
self.head = head.nextNode
count -= 1
}
if self.head == nil {
self.tail = nil
}
if self.count >= self.limit {
return false
}
let newNode = Node(time: Date())
if let tail {
tail.nextNode = newNode
self.tail = newNode
} else {
self.head = newNode
self.tail = newNode
}
count += 1
return true
}
}
This class is going to be critical from the security point of view – are there any issues in the above code?