目的
アプリを開発する上で、自社や外部のサーバーのAPIを叩くのは当たり前になってますが、連続で叩いちゃって迷惑をかけることもあるかと思います。
APIを叩く側で最初のAPIアクセスから指定した時間をブロックするようなコードを書いてみました。いえ、正確にはChatGPTに書かせてみました。
API実行後、10秒間ブロックします
この実装により、最初のリクエストが送信された後、cooldownPeriodで指定された秒数だけ新たなリクエストがブロックされます。タイマーが完了すると、isRequestAllowedフラグが再びtrueに設定され、リクエストの送信が可能になります。
.swift
import Foundation
import Alamofire
class ApiRateLimiter {
static let shared = ApiRateLimiter()
private var isRequestAllowed = true
private var cooldownTimer: Timer?
private let cooldownPeriod: TimeInterval
init(cooldownPeriod: TimeInterval = 10.0) { // x秒をデフォルト値とする
self.cooldownPeriod = cooldownPeriod
}
func request(_ url: URLConvertible, method: HTTPMethod = .get, parameters: Parameters? = nil, encoding: ParameterEncoding = URLEncoding.default, headers: HTTPHeaders? = nil, completion: @escaping (Result<Data?, AFError>) -> Void) {
guard isRequestAllowed else {
print("Request is blocked due to cooldown.")
completion(.failure(AFError.explicitlyCancelled))
return
}
isRequestAllowed = false
// Alamofireを使用してリクエストを実行
Alamofire.request(url, method: method, parameters: parameters, encoding: encoding, headers: headers).response { response in
completion(response.result)
}
// x秒間のクールダウンを開始
cooldownTimer?.invalidate()
cooldownTimer = Timer.scheduledTimer(withTimeInterval: cooldownPeriod, repeats: false) { [weak self] _ in
self?.isRequestAllowed = true
}
}
}
あとは、普通に利用するだけですので、APIごとに入れておくとサーバーに優しくなれると思います。
.swift
ApiRateLimiter.shared.request("https://api.example.com/data", method: .get, parameters: nil, encoding: URLEncoding.default, headers: nil) { result in
switch result {
case .success(let data):
print("Received data: \(String(describing: data))")
case .failure(let error):
print("Request failed with error: \(error)")
}
}