2017-05-14 12 views
2

私はHTTPクライアントでレート制限を実装するスマートな方法を探しています。 APIのレート制限がいずれかのリソースで1秒あたり5リクエストであるとします。今実装は次のようになります。Rate Limit with RxSwift

final class HTTPClient: HTTPClientProtocol { 

    func getUser() -> Observable<User> { 
     return Observable<User>.create { (observer) -> Disposable in 
      ... 
     } 
    } 

    func getProfile() -> Observable<Profile> { 
     return Observable<Profile>.create { (observer) -> Disposable in 
      ... 
     } 
    } 

    func getMessages() -> Observable<Messages> { 
     return Observable<Messages>.create { (observer) -> Disposable in 
      ... 
     } 
    } 

    func getFriends() -> Observable<Friends> { 
     return Observable<Friends>.create { (observer) -> Disposable in 
      ... 
     } 
    } 

} 

今、理想的に私は、必要に応じて、すべてのレート制限を気にすることなく、アプリケーション全体でこれらのメソッドを使用したいと思います。

1秒あたり5リクエストの例に戻る:最初の5つのリクエストはすぐに実行できます。しかしその後のすべてのリクエストは待たなければなりません。したがって、1秒のウィンドウ内では、最大で5回のリクエストを実行できます。他のすべてのリクエストは待機する必要があります。

これをRxSwiftで実行するスマートな方法はありますか?

+0

が重複する可能性を/ questions/43794392/rxswiftとの制限付き同時アクセスサービスクラス) –

+0

リンクされた質問には、「2要求/秒」の処理方法は示されていません。 – plu

+0

ああ...リンクされた答えは部分的に正しいです。サービスの専用スケジューラが必要ですが、カスタムスケジューラにする必要があります...カスタムスケジューラをまだ実行していないので、これについて考える必要があります。 –

答えて

0

カスタムスケジューラが必要です。

final class DelayScheduler: ImmediateSchedulerType { 

    init(delay: TimeInterval, queue: DispatchQueue = .main) { 
     self.queue = queue 
     dispatchDelay = delay 
    } 

    func schedule<StateType>(_ state: StateType, action: @escaping (StateType) -> Disposable) -> Disposable { 
     let cancel = SingleAssignmentDisposable() 
     lastDispatch = max(lastDispatch + dispatchDelay, .now()) 
     queue.asyncAfter(deadline: lastDispatch) { 
      guard cancel.isDisposed == false else { return } 
      cancel.setDisposable(action(state)) 
     } 
     return cancel 
    } 

    var lastDispatch: DispatchTime = .now() 
    let queue: DispatchQueue 
    let dispatchDelay: TimeInterval 
} 

その後、あなたはそのすべての観測は、このスケジューラに加入することによって、あなたのサービスを実装する:[RxSwiftとサービスクラスへの同時アクセスを制限する](http://stackoverflow.comの

final class HTTPClient: HTTPClientProtocol { 

    func getUser() -> Observable<User> { 
     return Observable<User>.create { (observer) -> Disposable in 
      ... 
     }.subscribeOn(scheduler) 
    } 

    func getProfile() -> Observable<Profile> { 
     return Observable<Profile>.create { (observer) -> Disposable in 
      ... 
     }.subscribeOn(scheduler) 
    } 

    func getMessages() -> Observable<Messages> { 
     return Observable<Messages>.create { (observer) -> Disposable in 
      ... 
     }.subscribeOn(scheduler) 
    } 

    func getFriends() -> Observable<Friends> { 
     return Observable<Friends>.create { (observer) -> Disposable in 
      ... 
     }.subscribeOn(scheduler) 
    } 

    let scheduler = DelayScheduler(delay: 0.5) 
} 
+0

ありがとうございます。残念ながら、これは私が探しているものではありません。あなたの解決策は、それが必要かどうかに関係なく、常にn + 1要求に遅延を与えます。実際のシナリオでは、1秒あたり5リクエストのレート制限があります。したがって、すぐに5つを実行することができますが、要求番号6では少し待つ必要があります。 – plu