[backend/core] Update user in background to avoid accessing a disposed DbContext

This commit is contained in:
Laura Hausmann 2024-02-17 18:50:04 +01:00
parent 19b004687d
commit b3d0c0f476
No known key found for this signature in database
GPG key ID: D044E84C5BE01605
3 changed files with 37 additions and 3 deletions

View file

@ -22,7 +22,7 @@ public static class ServiceExtensions
public static void AddServices(this IServiceCollection services)
{
// Transient = instantiated per request and class
//services.AddTransient<T>();
services.AddTransient<FollowupTaskService>();
// Scoped = instantiated per request
services

View file

@ -5,7 +5,12 @@ using Iceshrimp.Backend.Core.Services;
namespace Iceshrimp.Backend.Core.Federation.ActivityPub;
public class UserResolver(ILogger<UserResolver> logger, UserService userSvc, WebFingerService webFingerSvc)
public class UserResolver(
ILogger<UserResolver> logger,
UserService userSvc,
WebFingerService webFingerSvc,
FollowupTaskService followupTaskSvc
)
{
/*
* The full web finger algorithm:
@ -110,7 +115,14 @@ public class UserResolver(ILogger<UserResolver> logger, UserService userSvc, Web
try
{
return await userSvc.UpdateUserAsync(user).WaitAsync(TimeSpan.FromMilliseconds(1500));
var task = followupTaskSvc.ExecuteTask("UpdateUserAsync", async provider =>
{
var bgUserSvc = provider.GetRequiredService<UserService>();
await bgUserSvc.UpdateUserAsync(user);
});
// Return early, but continue execution in background
await task.WaitAsync(TimeSpan.FromMilliseconds(1500));
}
catch (Exception e)
{

View file

@ -0,0 +1,22 @@
namespace Iceshrimp.Backend.Core.Services;
public class FollowupTaskService(IServiceScopeFactory serviceScopeFactory)
{
public Task ExecuteTask(string taskName, Func<IServiceProvider, Task> work)
{
return Task.Run(async () =>
{
using var scope = serviceScopeFactory.CreateScope();
try
{
var provider = scope.ServiceProvider;
await work(provider);
}
catch (Exception e)
{
var logger = scope.ServiceProvider.GetRequiredService<ILogger<FollowupTaskService>>();
logger.LogError("Failed to execute background task {name}: {error}", taskName, e.ToString());
}
});
}
}