[backend/core] Use AsyncKeyedLock when fetching metadata for new instances (ISH-122)

This commit is contained in:
Laura Hausmann 2024-03-04 19:29:36 +01:00
parent 74424c4fb3
commit 75cf552453
No known key found for this signature in database
GPG key ID: D044E84C5BE01605

View file

@ -3,6 +3,7 @@ using Iceshrimp.Backend.Core.Database;
using Iceshrimp.Backend.Core.Database.Tables; using Iceshrimp.Backend.Core.Database.Tables;
using Iceshrimp.Backend.Core.Federation.WebFinger; using Iceshrimp.Backend.Core.Federation.WebFinger;
using Iceshrimp.Backend.Core.Helpers; using Iceshrimp.Backend.Core.Helpers;
using Microsoft.EntityFrameworkCore;
namespace Iceshrimp.Backend.Core.Services; namespace Iceshrimp.Backend.Core.Services;
@ -14,20 +15,36 @@ public class InstanceService(DatabaseContext db, HttpClient httpClient)
o.PoolInitialFill = 5; o.PoolInitialFill = 5;
}); });
public async Task<Instance> GetUpdatedInstanceMetadataAsync(string host, string webDomain) private async Task<Instance> GetUpdatedInstanceMetadataAsync(string host, string webDomain)
{ {
host = host.ToLowerInvariant(); host = host.ToLowerInvariant();
var instance = db.Instances.FirstOrDefault(p => p.Host == host); var instance = await db.Instances.FirstOrDefaultAsync(p => p.Host == host);
if (instance == null) if (instance == null)
{ {
instance = new Instance if (!KeyedLocker.IsInUse(host))
{ {
Id = IdHelpers.GenerateSlowflakeId(), using (await KeyedLocker.LockAsync(host))
Host = host, {
CaughtAt = DateTime.UtcNow, instance = new Instance
LastCommunicatedAt = DateTime.UtcNow, {
}; Id = IdHelpers.GenerateSlowflakeId(),
await db.AddAsync(instance); Host = host,
CaughtAt = DateTime.UtcNow,
LastCommunicatedAt = DateTime.UtcNow,
};
await db.AddAsync(instance);
await db.SaveChangesAsync();
}
}
else
{
using (await KeyedLocker.LockAsync(host))
{
instance = await db.Instances.FirstOrDefaultAsync(p => p.Host == host);
}
if (instance == null) throw new Exception("Failed to get instance metadata for {host}");
}
} }
if (instance.NeedsUpdate && !KeyedLocker.IsInUse(host)) if (instance.NeedsUpdate && !KeyedLocker.IsInUse(host))
@ -51,13 +68,14 @@ public class InstanceService(DatabaseContext db, HttpClient httpClient)
instance.SoftwareVersion = nodeinfo.Software?.Version; instance.SoftwareVersion = nodeinfo.Software?.Version;
instance.ThemeColor = nodeinfo.Metadata?.ThemeColor; instance.ThemeColor = nodeinfo.Metadata?.ThemeColor;
} }
await db.SaveChangesAsync();
} }
} }
await db.SaveChangesAsync();
return instance; return instance;
} }
public async Task<Instance> GetUpdatedInstanceMetadataAsync(User user) public async Task<Instance> GetUpdatedInstanceMetadataAsync(User user)
{ {
if (user.Host == null || user.Uri == null) throw new Exception("Can't fetch instance metadata for local user"); if (user.Host == null || user.Uri == null) throw new Exception("Can't fetch instance metadata for local user");