internal void UnlockSocket(SocketLockToken token) // TODO : доделать { switch (token.type) { case LockType.Receive: if (Interlocked.Decrement(ref receivingLockersCount) == 0) { socketReceiveLocked = false; if (receiveKernelWaitingsCount != 0) { receiveARE.Set(); } } break; case LockType.Send: SocketSendLockToken sendToken = token as SocketSendLockToken; if (sendToken.IsHardLocked) { if (Interlocked.Decrement(ref sendingHardLockersCount) == 0) { socketSendHardLocked = false; } } if (Interlocked.Decrement(ref sendingLockersCount) == 0) { socketSendSoftLocked = false; if (sendKernelWaitingsCount != 0) { sendARE.Set(); } } break; case LockType.Suspend: if (Interlocked.Decrement(ref receivingLockersCount) == 0) { socketReceiveLocked = false; if (receiveKernelWaitingsCount != 0) { receiveARE.Set(); } } if (Interlocked.Decrement(ref sendingHardLockersCount) == 0) { socketSendHardLocked = false; } if (Interlocked.Decrement(ref sendingLockersCount) == 0) { socketSendSoftLocked = false; if (sendKernelWaitingsCount != 0) { sendARE.Set(); } } break; } }
private async void ListenToRateLimit() { int oneMinute = 60000; //From ms int limit = 120; Stopwatch stopwatch = new Stopwatch(); while (true) { stopwatch.Start(); while (stopwatch.ElapsedMilliseconds < oneMinute) { // Здесь может возникнуть вопрос "А почему мы используем ограничение равное 118?" // Ответом на этот вопрос будет то, что ограничение отправляемых к Gateway дискорда // Равняется 120 запросов\минута. Но некоторые запросы, такие как Hearbeat // Необходимо отправлять каждые, в данный момент времени, 41.5 секунд. // Для решения это проблемы я ввёл ограничение на (limit - 2) запроса, дабы // 2 запроса остались в запасе для приоритетных запросов. if (payloadSentLastMinute == limit - 2) //TODO : вынести хардлок в конфиг? { using (SocketSendLockToken token = socketHelper.GetSendingLock()) { while (stopwatch.ElapsedMilliseconds < oneMinute) { if (payloadSentLastMinute == limit) { token.HardLockSocket(); TimeSpan msToWait = TimeSpan.FromMilliseconds(oneMinute - stopwatch.ElapsedMilliseconds); //Через этот отрезок времени наступит новая минута => можно сбрасывать счётчик; ReachedRateLimit(msToWait); await Task.Delay(msToWait); break; } } } } //TODO : здесь всё же может быть проблема с тем, что количество пакетов будет == 120, даже с HighPriority } Interlocked.Exchange(ref payloadSentLastMinute, 0); stopwatch.Restart(); } }