2016-08-05 5 views
2

数値を追加する単一のメソッドを持つ単純な電卓サービスを作成したいと考えています。このAddメソッドはasyncである必要があり、同時に実行される同時呼び出しの数を制限する必要があります。たとえば、1秒あたり最大5同時コール。レート制限を超えた場合、コールは例外をスローする必要があります。Observablesでレート制限APIを構築するにはどうすればよいですか?

public class RateLimitingCalculator 
{ 
    public async Task<int> Add(int a, int b) 
    { 
     //... 
    } 
} 

任意のアイデア:

クラスは次のようにすべきですか? Reactive Extensionsで実装したいのですが、別の戦略を使用する方が良い場合は、それに固執します。 ありがとうございます!

+0

[this post](http://stackoverflow.com/a/36933908/3407841)にはいくつかのアイデアがあります。 – leetibbett

+0

あなたは本当にモナドの混合を避けるべきです。私はあなたがこの署名を持っていれば、これを推論する方が簡単だと思う: 'public IObservable Add(IObservable 値)'。 – Enigmativity

+0

@Enigmativity "モナドの混合を避ける"とはどういう意味ですか?また、Rxを使用してAPIのレートを制限することが理にかなっていると思いますか? – SuperJMN

答えて

1

あなたのメソッドをpublic IObservable<int> Add(IObservable<Tuple<int, int>> values)のようなものに書き換えることができない限り、Rxを使うのは意味がないと思います。

レートリミットの懸念を別のクラスに分けることです。そうすれば、あなたのコードは次のようになります:

public class RateLimitingCalculator 
{ 
    private RateLimiter rateLimiter = new RateLimiter(5, TimeSpan.FromSeconds(1)); 

    public async Task<int> Add(int a, int b) 
    { 
     rateLimiter.ThrowIfRateExceeded(); 

     //... 
    } 
} 

RateLimiterの実装では、あなたの正確な要件に依存しますが、非常に単純ではなく、スレッドセーフバージョンは、次のようになります。

class RateLimiter 
{ 
    private readonly int rate; 
    private readonly TimeSpan perTime; 

    private DateTime secondStart = DateTime.MinValue; 
    private int count = 0; 

    public RateLimiter(int rate, TimeSpan perTime) 
    { 
     this.rate = rate; 
     this.perTime = perTime; 
    } 

    public void ThrowIfRateExceeded() 
    { 
     var now = DateTime.UtcNow; 

     if (now - secondStart > perTime) 
     { 
      secondStart = now; 
      count = 1; 
      return; 
     } 

     if (count >= rate) 
      throw new RateLimitExceededException(); 

     count++; 
    } 
} 
+0

私はまた、反対に、利率の低いAPIを可能な限り透過的に使用したいと考えています:http://stackoverflow.com/questions/38675713/wrapping-rate-limiting-api-callあなたが手伝ってくれるかもしれない。巨大な感謝! – SuperJMN

関連する問題