有些網站,例如AI繪圖,因為單一 request 會花較長時間,所以會限制使用者不能重覆送 request,或是在一個 request 結束後,在一定時間內不能再送第二次,本篇文章會提出一個概念性想法。

它的設定也很直覺,程式碼如下:

public class RequestManager
{
    private static RequestManager instance;

    public static RequestManager Instance
    {
        get
        {
            if (instance == null)
            {
                instance = new RequestManager();
            }
            return instance;
        }
    }

    private RequestManager()
    {
        _requestDictionary = new ConcurrentDictionary<string, RequestModel>();
        _waitingtimeDictionary = new ConcurrentDictionary<string, DateTime>();
    }

    private ConcurrentDictionary<string, RequestModel> _requestDictionary;
    private ConcurrentDictionary<string, DateTime> _waitingtimeDictionary;
    private const int waitingseconds = 10;

    public bool CheckTimespan(string token)
    {
        if (_waitingtimeDictionary.ContainsKey(token))
        {
            DateTime previousTime = _waitingtimeDictionary[token];
            DateTime dt = DateTime.Now;
            TimeSpan timeOffset = dt - previousTime;
            if (timeOffset.Seconds > waitingseconds)
            {
                _waitingtimeDictionary.TryRemove(token, out dt);
                return true;
            }
            else
            {
                return false;
            }
        }

        return true;
    }

    public bool ReceiveRequest(RequestModel requestModel)
    {
        if (!_requestDictionary.ContainsKey(requestModel.Token))
        {
            _requestDictionary.TryAdd(requestModel.Token, requestModel);
            _waitingtimeDictionary.TryAdd(requestModel.Token, DateTime.Now);
            return true;
        }

        if (_waitingtimeDictionary.ContainsKey(requestModel.Token))
        {
            return CheckTimespan(requestModel.Token);
        }

        return true;
    }

    public bool CanSendRequest(string token)
    {
        return CheckTimespan(token);
    }

    public void RemoveRequest(string token) 
    {
        _requestDictionary.TryRemove(token, out RequestModel requestModel);
        _waitingtimeDictionary.TryRemove(token, out DateTime dt);
    }
}

主要的概念在於宣告兩個 Dictionary,一個儲存 request,一個儲存收到 request 的時間。

public bool ReceiveRequest(RequestModel requestModel)
{
    if (!_requestDictionary.ContainsKey(requestModel.Token))
    {
        _requestDictionary.TryAdd(requestModel.Token, requestModel);
        _waitingtimeDictionary.TryAdd(requestModel.Token, DateTime.Now);
        return true;
    }

    if (_waitingtimeDictionary.ContainsKey(requestModel.Token))
    {
        return CheckTimespan(requestModel.Token);
    }

    return true;
}

而在 request 結束後,把它刪除:

public void RemoveRequest(string token) 
{
    _requestDictionary.TryRemove(token, out RequestModel requestModel);
    _waitingtimeDictionary.TryRemove(token, out DateTime dt);
}

另一個比較重要的就是,檢查時間是否到了:

public bool CheckTimespan(string token)
{
    if (_waitingtimeDictionary.ContainsKey(token))
    {
        DateTime previousTime = _waitingtimeDictionary[token];
        DateTime dt = DateTime.Now;
        TimeSpan timeOffset = dt - previousTime;
        if (timeOffset.Seconds > waitingseconds)
        {
            _waitingtimeDictionary.TryRemove(token, out dt);
            return true;
        }
        else
        {
            return false;
        }
    }

    return true;
}