[backend/core] Fix long application exit times by passing IHostApplicationLifetime.ApplicationStopping to long-running awaits
This commit is contained in:
parent
5da6b39f33
commit
1c8df9879d
3 changed files with 15 additions and 11 deletions
|
@ -65,7 +65,7 @@ public class UserResolver(
|
|||
}
|
||||
|
||||
var finalAcct = fingerRes.Subject;
|
||||
var finalUri = fingerRes.Links.FirstOrDefault(p => p.Rel == "self" && p.Type == "application/activity+json")
|
||||
var finalUri = fingerRes.Links.FirstOrDefault(p => p is { Rel: "self", Type: "application/activity+json" })
|
||||
?.Href ??
|
||||
throw new GracefulException("Final AP URI was null");
|
||||
|
||||
|
|
|
@ -19,14 +19,14 @@ namespace Iceshrimp.Backend.Core.Federation.WebFinger;
|
|||
//FIXME: handle cursed person/group acct collisions like https://lemmy.ml/.well-known/webfinger?resource=acct:linux@lemmy.ml
|
||||
//FIXME: also check if the query references the local instance in other ways (e.g. @user@{WebDomain}, @user@{AccountDomain}, https://{WebDomain}/..., etc)
|
||||
|
||||
public class WebFingerService(HttpClient client, HttpRequestService httpRqSvc)
|
||||
public class WebFingerService(HttpClient client, HttpRequestService httpRqSvc, IHostApplicationLifetime appLifetime)
|
||||
{
|
||||
public async Task<WebFingerResponse?> ResolveAsync(string query)
|
||||
{
|
||||
(query, var proto, var domain) = ParseQuery(query);
|
||||
var webFingerUrl = await GetWebFingerUrlAsync(query, proto, domain);
|
||||
|
||||
using var cts = new CancellationTokenSource();
|
||||
using var cts = CancellationTokenSource.CreateLinkedTokenSource(appLifetime.ApplicationStopping);
|
||||
cts.CancelAfter(TimeSpan.FromSeconds(10));
|
||||
|
||||
var req = httpRqSvc.Get(webFingerUrl, ["application/jrd+json", "application/json"]);
|
||||
|
|
|
@ -23,7 +23,8 @@ public class AuthorizedFetchMiddleware(
|
|||
UserService userSvc,
|
||||
SystemUserService systemUserSvc,
|
||||
ActivityPub.FederationControlService fedCtrlSvc,
|
||||
ILogger<AuthorizedFetchMiddleware> logger
|
||||
ILogger<AuthorizedFetchMiddleware> logger,
|
||||
IHostApplicationLifetime appLifetime
|
||||
) : IMiddleware
|
||||
{
|
||||
private static readonly JsonSerializerSettings JsonSerializerSettings =
|
||||
|
@ -36,6 +37,7 @@ public class AuthorizedFetchMiddleware(
|
|||
if (attribute != null && config.Value.AuthorizedFetch)
|
||||
{
|
||||
var request = ctx.Request;
|
||||
var ct = appLifetime.ApplicationStopping;
|
||||
|
||||
//TODO: cache this somewhere
|
||||
var instanceActorUri = $"/users/{(await systemUserSvc.GetInstanceActorAsync()).Id}";
|
||||
|
@ -62,15 +64,17 @@ public class AuthorizedFetchMiddleware(
|
|||
supressLog: true);
|
||||
|
||||
// First, we check if we already have the key
|
||||
key = await db.UserPublickeys.Include(p => p.User).FirstOrDefaultAsync(p => p.KeyId == sig.KeyId);
|
||||
key = await db.UserPublickeys.Include(p => p.User)
|
||||
.FirstOrDefaultAsync(p => p.KeyId == sig.KeyId, cancellationToken: ct);
|
||||
|
||||
// If we don't, we need to try to fetch it
|
||||
if (key == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var user = await userResolver.ResolveAsync(sig.KeyId);
|
||||
key = await db.UserPublickeys.Include(p => p.User).FirstOrDefaultAsync(p => p.User == user);
|
||||
var user = await userResolver.ResolveAsync(sig.KeyId).WaitAsync(ct);
|
||||
key = await db.UserPublickeys.Include(p => p.User)
|
||||
.FirstOrDefaultAsync(p => p.User == user, cancellationToken: ct);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
@ -121,7 +125,7 @@ public class AuthorizedFetchMiddleware(
|
|||
if (!ActivityPub.ActivityFetcherService.IsValidActivityContentType(contentType))
|
||||
throw new Exception("Request body is not an activity");
|
||||
|
||||
var body = await new StreamReader(request.Body).ReadToEndAsync();
|
||||
var body = await new StreamReader(request.Body).ReadToEndAsync(ct);
|
||||
request.Body.Seek(0, SeekOrigin.Begin);
|
||||
var deserialized = JsonConvert.DeserializeObject<JObject?>(body);
|
||||
var expanded = LdHelpers.Expand(deserialized);
|
||||
|
@ -140,14 +144,14 @@ public class AuthorizedFetchMiddleware(
|
|||
key = null;
|
||||
key = await db.UserPublickeys
|
||||
.Include(p => p.User)
|
||||
.FirstOrDefaultAsync(p => p.User.Uri == activity.Actor.Id);
|
||||
.FirstOrDefaultAsync(p => p.User.Uri == activity.Actor.Id, cancellationToken: ct);
|
||||
|
||||
if (key == null)
|
||||
{
|
||||
var user = await userResolver.ResolveAsync(activity.Actor.Id);
|
||||
var user = await userResolver.ResolveAsync(activity.Actor.Id).WaitAsync(ct);
|
||||
key = await db.UserPublickeys
|
||||
.Include(p => p.User)
|
||||
.FirstOrDefaultAsync(p => p.User == user);
|
||||
.FirstOrDefaultAsync(p => p.User == user, cancellationToken: ct);
|
||||
|
||||
if (key == null)
|
||||
throw new Exception($"Failed to fetch public key for user {activity.Actor.Id}");
|
||||
|
|
Loading…
Add table
Reference in a new issue