public double BlockChance => 1.0 - WindowPercentage; // slowly unblock in the second half /// <summary> /// Normal, non-errornous call attempt. Returns null if an error occured, or if the call was throttled /// </summary> public async Task <T> CallAsync <T>(Func <Task <T> > func) { // Still blocking? if (IsBlocking) { // Roll a dice on how many requests to let pass if (Rand.ChanceDouble(BlockChance)) { Interlocked.Increment(ref numBlockedRequestsInWindow); //BlockedRequests.Mark(); return(default(T)); } } // Clear a window otherwise? else if (beginningOfBlockOutWindow != null) { Interlocked.Exchange(ref numErrors, 0); beginningOfBlockOutWindow = null; Log.Warn($"ErrorRateLimiter is LEAVING blocking mode (blocked {numBlockedRequestsInWindow} requests)"); } try { return(await func()); } catch (Exception ex) { Log.Warn($"ErrorRateLimiter.Call caught: {ex.Message}"); IncrementErrors(); return(default(T)); } }
/// <summary> /// Aquires a broadcast Queue /// </summary> public static DispatchingQueue Acquire(Action <GameClient> tcpAction, double dispatchChance = 1) { var q = QueuePool.Pop(); q.forTcp = tcpAction; q.shouldDispatch = GameServer.DispatchEnable && Rand.ChanceDouble(dispatchChance); return(q); }