refactor!: rename the project from Monitor to MoShiro [CI]
ci/woodpecker/push/main-amd64-build Pipeline was successful
ci/woodpecker/push/main-amd64-build Pipeline was successful
Namespaces, assemblies, solution, binaries, images, systemd units, config paths, environment variables, protocol methods and the Linux user are all renamed. Breaking: existing databases, node identities and installed units must be recreated.
This commit is contained in:
1 parent
27ac7fb787
commit
2e146d4da7
309 files changed
+1565
-1572
No files matched your search
@@ -0,0 +1,57 @@
|
||||
using System.Collections.Concurrent;
|
||||
|
||||
namespace MoShiro.Backend.Application;
|
||||
|
||||
/// <summary>登录限流:每个来源在滑动的一分钟内最多尝试若干次。</summary>
|
||||
public sealed class LoginRateLimiter
|
||||
{
|
||||
private readonly ConcurrentDictionary<string, Queue<long>> _attempts = new();
|
||||
private readonly BackendOptions _options;
|
||||
private readonly TimeProvider _time;
|
||||
|
||||
public LoginRateLimiter(BackendOptions options, TimeProvider time)
|
||||
{
|
||||
_options = options;
|
||||
_time = time;
|
||||
}
|
||||
|
||||
/// <summary>登记一次尝试;超限时返回 false 与建议的重试等待秒数。</summary>
|
||||
public bool TryAcquire(string source, out int retryAfterSeconds)
|
||||
{
|
||||
long now = _time.GetUtcNow().ToUnixTimeMilliseconds();
|
||||
Queue<long> queue = _attempts.GetOrAdd(source, _ => new Queue<long>());
|
||||
lock (queue)
|
||||
{
|
||||
while (queue.Count > 0 && now - queue.Peek() >= 60_000)
|
||||
{
|
||||
queue.Dequeue();
|
||||
}
|
||||
|
||||
if (queue.Count >= _options.LoginAttemptsPerMinute)
|
||||
{
|
||||
retryAfterSeconds = (int)Math.Max(1, (60_000 - (now - queue.Peek()) + 999) / 1000);
|
||||
return false;
|
||||
}
|
||||
|
||||
queue.Enqueue(now);
|
||||
retryAfterSeconds = 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>清理很久没有尝试的来源,避免字典无限增长。</summary>
|
||||
public void Prune()
|
||||
{
|
||||
long now = _time.GetUtcNow().ToUnixTimeMilliseconds();
|
||||
foreach ((string key, Queue<long> queue) in _attempts)
|
||||
{
|
||||
lock (queue)
|
||||
{
|
||||
if (queue.Count == 0 || now - queue.Peek() >= 60_000)
|
||||
{
|
||||
_attempts.TryRemove(key, out _);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user