Skip to content

Commit 985eaf6

Browse files
committed
Un-async AniDB and use a lock, which supports recursion. Async apparently makes that extremely difficult, and I'm not rewriting the entire pipeline right now
1 parent 83461a9 commit 985eaf6

File tree

17 files changed

+82
-126
lines changed

17 files changed

+82
-126
lines changed

Shoko.Server/API/v1/Implementations/ShokoServiceImplementation/ShokoServiceImplementation.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -649,7 +649,7 @@ public string TestAniDBConnection()
649649
settings.AniDb.UDPServerPort, settings.AniDb.ClientPort);
650650

651651
log += "Login..." + Environment.NewLine;
652-
if (handler.Login().Result)
652+
if (handler.Login())
653653
{
654654
log += "Login Success!" + Environment.NewLine;
655655
log += "Logout..." + Environment.NewLine;

Shoko.Server/API/v2/Modules/Core.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -206,13 +206,13 @@ public async Task<ActionResult> TestAniDB()
206206
{
207207
var handler = HttpContext.RequestServices.GetRequiredService<IUDPConnectionHandler>();
208208
handler.ForceLogout();
209-
await handler.CloseConnections();
209+
handler.CloseConnections();
210210

211-
await handler.Init(_settings.AniDb.Username, _settings.AniDb.Password,
211+
handler.Init(_settings.AniDb.Username, _settings.AniDb.Password,
212212
_settings.AniDb.UDPServerAddress,
213213
_settings.AniDb.UDPServerPort, _settings.AniDb.ClientPort);
214214

215-
if (await handler.Login())
215+
if (handler.Login())
216216
{
217217
handler.ForceLogout();
218218
return APIStatus.OK();

Shoko.Server/API/v2/Modules/Init.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -278,15 +278,15 @@ public async Task<ActionResult> TestAniDB()
278278
{
279279
var handler = HttpContext.RequestServices.GetRequiredService<IUDPConnectionHandler>();
280280
handler.ForceLogout();
281-
await handler.CloseConnections();
281+
handler.CloseConnections();
282282

283283
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(_settings.Culture);
284284

285-
await handler.Init(_settings.AniDb.Username, _settings.AniDb.Password,
285+
handler.Init(_settings.AniDb.Username, _settings.AniDb.Password,
286286
_settings.AniDb.UDPServerAddress,
287287
_settings.AniDb.UDPServerPort, _settings.AniDb.ClientPort);
288288

289-
if (!await handler.Login()) return APIStatus.BadRequest("Failed to log in");
289+
if (!handler.Login()) return APIStatus.BadRequest("Failed to log in");
290290
handler.ForceLogout();
291291

292292
return APIStatus.OK();

Shoko.Server/API/v3/Controllers/DebugController.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -109,22 +109,22 @@ public async Task<ActionResult> FetchAniDBMessage(int id)
109109
/// <param name="request">The AniDB UDP Request to make.</param>
110110
/// <returns>An AniDB UDP Response.</returns>
111111
[HttpPost("AniDB/UDP/Call")]
112-
public async Task<AnidbUdpResponse> CallAniDB([FromBody] AnidbUdpRequest request)
112+
public AnidbUdpResponse CallAniDB([FromBody] AnidbUdpRequest request)
113113
{
114114
try
115115
{
116116
var token = HttpContext.RequestAborted;
117117
_logger.LogDebug("Got command {Command}", request.Command);
118118
if (request.NeedAuth)
119119
{
120-
if (string.IsNullOrEmpty(_udpHandler.SessionID) && !await _udpHandler.Login())
120+
if (string.IsNullOrEmpty(_udpHandler.SessionID) && !_udpHandler.Login())
121121
return new() { Code = UDPReturnCode.NOT_LOGGED_IN };
122122
request.Payload.Add("s", _udpHandler.SessionID);
123123
}
124124

125125
var fullResponse = request.Unsafe ?
126-
await _udpHandler.SendDirectly(request.Command, isPing: request.IsPing, isLogout: request.IsLogout, token: token) :
127-
await _udpHandler.Send(request.Command, token: token);
126+
_udpHandler.SendDirectly(request.Command, isPing: request.IsPing, isLogout: request.IsLogout) :
127+
_udpHandler.Send(request.Command);
128128
var decodedParts = fullResponse.Split('\n');
129129
var decodedResponse = string.Join('\n',
130130
fullResponse.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)

Shoko.Server/API/v3/Controllers/SettingsController.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ public ActionResult SetSettings([FromBody] JsonPatchDocument<ServerSettings> set
7070
/// <param name="credentials">POST the body as a <see cref="Credentials"/> object</param>
7171
/// <returns></returns>
7272
[HttpPost("AniDB/TestLogin")]
73-
public async Task<ActionResult> TestAniDB([FromBody] Credentials credentials)
73+
public ActionResult TestAniDB([FromBody] Credentials credentials)
7474
{
7575
_logger.LogInformation("Testing AniDB Login and Connection");
7676
if (string.IsNullOrWhiteSpace(credentials.Username))
@@ -87,10 +87,10 @@ public async Task<ActionResult> TestAniDB([FromBody] Credentials credentials)
8787

8888
var settings = SettingsProvider.GetSettings();
8989
if (!_udpHandler.IsAlive)
90-
await _udpHandler.Init(credentials.Username, credentials.Password, settings.AniDb.UDPServerAddress, settings.AniDb.UDPServerPort, settings.AniDb.ClientPort);
90+
_udpHandler.Init(credentials.Username, credentials.Password, settings.AniDb.UDPServerAddress, settings.AniDb.UDPServerPort, settings.AniDb.ClientPort);
9191
else _udpHandler.ForceLogout();
9292

93-
if (!await _udpHandler.TestLogin(credentials.Username, credentials.Password))
93+
if (!_udpHandler.TestLogin(credentials.Username, credentials.Password))
9494
{
9595
_logger.LogInformation("Failed AniDB Login and Connection");
9696
return ValidationProblem("Failed to log in.", "Connection");

Shoko.Server/Providers/AniDB/AniDBRateLimiter.cs

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
using System;
22
using System.Diagnostics;
33
using System.Threading;
4-
using System.Threading.Tasks;
54
using Microsoft.Extensions.Logging;
65
using Shoko.Plugin.Abstractions;
76
using Shoko.Plugin.Abstractions.Events;
@@ -15,8 +14,7 @@ namespace Shoko.Server.Providers.AniDB;
1514
public abstract class AniDBRateLimiter
1615
{
1716
private readonly ILogger _logger;
18-
19-
private readonly SemaphoreSlim _lock = new(1, 1);
17+
private readonly object _lock = new();
2018

2119
private readonly object _settingsLock = new();
2220

@@ -140,9 +138,9 @@ private void ResetRate()
140138
_logger.LogTrace("Rate is reset. Active time was {Time} ms", elapsedTime);
141139
}
142140

143-
public async Task<T> EnsureRateAsync<T>(Func<Task<T>> action, bool forceShortDelay = false)
141+
public T EnsureRate<T>(Func<T> action, bool forceShortDelay = false)
144142
{
145-
await _lock.WaitAsync();
143+
lock (_lock)
146144
try
147145
{
148146
var delay = _requestWatch.ElapsedMilliseconds;
@@ -153,22 +151,21 @@ public async Task<T> EnsureRateAsync<T>(Func<Task<T>> action, bool forceShortDel
153151
{
154152
_logger.LogTrace("Time since last request is {Delay} ms, not throttling", delay);
155153
_logger.LogTrace("Sending AniDB command");
156-
return await action();
154+
return action();
157155
}
158156

159157
// add 50ms for good measure
160158
var waitTime = currentDelay - (int)delay + 50;
161159

162-
_logger.LogTrace("Time since last request is {Delay} ms, throttling for {Time}", delay, waitTime);
163-
await Task.Delay(waitTime);
160+
_logger.LogTrace("Time since last request is {Delay} ms, throttling for {Time}ms", delay, waitTime);
161+
Thread.Sleep(waitTime);
164162

165163
_logger.LogTrace("Sending AniDB command");
166-
return await action();
164+
return action();
167165
}
168166
finally
169167
{
170168
_requestWatch.Restart();
171-
_lock.Release();
172169
}
173170
}
174171
}

Shoko.Server/Providers/AniDB/HTTP/AniDBHttpConnectionHandler.cs

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,7 @@ public AniDBHttpConnectionHandler(ILoggerFactory loggerFactory, HttpRateLimiter
3535
_httpClient.BaseAddress = new Uri(Utils.SettingsProvider.GetSettings().AniDb.HTTPServerUrl);
3636
}
3737

38-
public async Task<HttpResponse<string>> GetHttp(string url)
39-
{
40-
var response = await GetHttpDirectly(url);
41-
42-
return response;
43-
}
44-
45-
public async Task<HttpResponse<string>> GetHttpDirectly(string url)
38+
public HttpResponse<string> GetHttp(string url)
4639
{
4740
if (IsBanned)
4841
{
@@ -53,12 +46,12 @@ public async Task<HttpResponse<string>> GetHttpDirectly(string url)
5346
};
5447
}
5548

56-
var response = await RateLimiter.EnsureRateAsync(async () =>
49+
var response = RateLimiter.EnsureRate(() =>
5750
{
58-
using var response = await _httpClient.GetAsync(url);
51+
using var response = _httpClient.GetAsync(url).Result;
5952
response.EnsureSuccessStatusCode();
6053

61-
var output = await response.Content.ReadAsStringAsync();
54+
var output = response.Content.ReadAsStringAsync().Result;
6255

6356
if (CheckForBan(output))
6457
{

Shoko.Server/Providers/AniDB/HTTP/HttpRequest.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ protected HttpRequest(IHttpConnectionHandler handler, ILoggerFactory loggerFacto
2727
public virtual HttpResponse<T> Send()
2828
{
2929
Command = BaseCommand.Trim();
30-
var rawResponse = _handler.GetHttp(Command).ConfigureAwait(true).GetAwaiter().GetResult();
30+
var rawResponse = _handler.GetHttp(Command);
3131
var response = ParseResponse(rawResponse).Result;
3232
PostExecute(response);
3333
return response;

Shoko.Server/Providers/AniDB/Interfaces/IHttpConnectionHandler.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@ namespace Shoko.Server.Providers.AniDB.Interfaces;
55

66
public interface IHttpConnectionHandler : IConnectionHandler
77
{
8-
Task<HttpResponse<string>> GetHttp(string url);
8+
HttpResponse<string> GetHttp(string url);
99
}
Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
using System;
2-
using System.Threading;
3-
using System.Threading.Tasks;
42

53
namespace Shoko.Server.Providers.AniDB.Interfaces;
64

@@ -13,17 +11,17 @@ public interface IUDPConnectionHandler : IConnectionHandler
1311
event EventHandler LoginFailed;
1412
bool SetCredentials(string username, string password);
1513
bool ValidAniDBCredentials(string user, string pass);
16-
Task<bool> Login();
14+
bool Login();
1715
void ForceLogout();
1816
void ClearSession();
19-
Task CloseConnections();
20-
Task ForceReconnection();
17+
void CloseConnections();
18+
void ForceReconnection();
2119
void StartBackoffTimer(int time, string message);
22-
Task<bool> Init();
23-
Task<bool> Init(string username, string password, string serverName, ushort serverPort, ushort clientPort);
24-
Task<bool> TestLogin(string username, string password);
20+
bool Init();
21+
bool Init(string username, string password, string serverName, ushort serverPort, ushort clientPort);
22+
bool TestLogin(string username, string password);
2523

26-
Task<string> SendDirectly(string command, bool needsUnicode = true, bool isPing = false, bool isLogout = false, CancellationToken token = new());
24+
string SendDirectly(string command, bool needsUnicode = true, bool isPing = false, bool isLogout = false);
2725

28-
Task<string> Send(string command, bool needsUnicode = true, CancellationToken token = new());
26+
string Send(string command, bool needsUnicode = true);
2927
}

0 commit comments

Comments
 (0)